home *** CD-ROM | disk | FTP | other *** search
/ Cream of the Crop 26 / Cream of the Crop 26.iso / os2 / pvm34b3.zip / pvm34b3 / pvm3 / src / lpvm.c < prev    next >
Text File  |  1997-08-08  |  81KB  |  3,567 lines

  1.  
  2. static char rcsid[] =
  3.     "$Id: lpvm.c,v 1.30 1997/06/27 18:04:17 pvmsrc Exp $";
  4.  
  5. /*
  6.  *         PVM version 3.4:  Parallel Virtual Machine System
  7.  *               University of Tennessee, Knoxville TN.
  8.  *           Oak Ridge National Laboratory, Oak Ridge TN.
  9.  *                   Emory University, Atlanta GA.
  10.  *      Authors:  J. J. Dongarra, G. E. Fagg, M. Fischer
  11.  *          G. A. Geist, J. A. Kohl, R. J. Manchek, P. Mucci,
  12.  *         P. M. Papadopoulos, S. L. Scott, and V. S. Sunderam
  13.  *                   (C) 1997 All Rights Reserved
  14.  *
  15.  *                              NOTICE
  16.  *
  17.  * Permission to use, copy, modify, and distribute this software and
  18.  * its documentation for any purpose and without fee is hereby granted
  19.  * provided that the above copyright notice appear in all copies and
  20.  * that both the copyright notice and this permission notice appear in
  21.  * supporting documentation.
  22.  *
  23.  * Neither the Institutions (Emory University, Oak Ridge National
  24.  * Laboratory, and University of Tennessee) nor the Authors make any
  25.  * representations about the suitability of this software for any
  26.  * purpose.  This software is provided ``as is'' without express or
  27.  * implied warranty.
  28.  *
  29.  * PVM version 3 was funded in part by the U.S. Department of Energy,
  30.  * the National Science Foundation and the State of Tennessee.
  31.  */
  32.  
  33. /*
  34.  *    lpvm.c
  35.  *
  36.  *    Libpvm core for unix environment.
  37.  *
  38. $Log: lpvm.c,v $
  39.  * Revision 1.30  1997/06/27  18:04:17  pvmsrc
  40.  * Integrated WIN32 changes.
  41.  *
  42.  * Revision 1.29  1997/06/12  20:10:37  pvmsrc
  43.  * Made sure all communications for TC_* task control messages
  44.  *     use the SYSCTX_TC system context.
  45.  *     - some messages being sent in default context...  D-Oh...
  46.  *
  47.  * Revision 1.28  1997/05/07  21:19:23  pvmsrc
  48.  * swapped logic around SOCKLENISINT so that it is now
  49.  * the default path and SOCKLENISUINT is the compile-time
  50.  * selected path.
  51.  *
  52.  * Now, AIX 4.1 will have to remove SOCKLENISUINT from
  53.  * their AIXxxx.def configure files.
  54.  *
  55.  * Revision 1.27  1997/05/07  18:37:13  pvmsrc
  56.  * AIX 3.2 vs 4.1 vs 4.2 problems resolved (I hope)
  57.  * Define oslen as size_t with compile flag SOCKLENISINT
  58.  * for AIX 4.1 to explicitly set to int.
  59.  * To use flag - set in conf/AIX46K.def.
  60.  * Tested with cc and gcc on all 3 OS versions.
  61.  *
  62.  * Revision 1.26  1997/05/05  15:19:40  pvmsrc
  63.  *     context was not being set in pvmmcast.
  64.  *
  65.  * Revision 1.25  1997/05/01  14:11:46  pvmsrc
  66.  * SGI Compiler Warning Cleanup.
  67.  *
  68.  * Revision 1.24  1997/04/30  21:26:00  pvmsrc
  69.  * SGI Compiler Warning Cleanup.
  70.  *
  71.  * Revision 1.23  1997/04/29  20:29:12  pvmsrc
  72.  *     Support new calling sequences defined in mppmsg.h
  73.  *
  74.  * Revision 1.22  1997/04/25  19:21:18  pvmsrc
  75.  * Handle inplace bodies of zero length correctly
  76.  *
  77.  * Revision 1.21  1997/04/24  21:06:59  pvmsrc
  78.  * Excised unused variables.
  79.  * Support for pvm_psend/precv constructs
  80.  *
  81.  * Revision 1.20  1997/04/21  14:58:28  pvmsrc
  82.  * Changed #ifdefs that checked IMA_RS6K,IMA_SP2MPI & IMA_AIX46K
  83.  *     to see if select.h was needed into single define NEEDSSELECTH.
  84.  *     New archs need to set this in conf/
  85.  *
  86.  * Revision 1.19  1997/04/07  21:09:17  pvmsrc
  87.  * pvm_addmhf() - new paramter interface
  88.  *
  89.  * Revision 1.18  1997/04/03  19:23:13  pvmsrc
  90.  * Added context for TM_xxx messages
  91.  *
  92.  * Revision 1.17  1997/04/01  21:28:11  pvmsrc
  93.  * Damn Damn Damn.
  94.  *     - pvm_recvinfo() returns a bufid, not an index.  Damn.
  95.  *
  96.  * Revision 1.16  1997/04/01  20:48:17  pvmsrc
  97.  * Fixed tracer mbox usage:
  98.  *     - pvm_getinfo() -> pvm_recvinfo(), new semantics handled (recvinfo
  99.  *         sets rbuf implicitly, a la pvm_recv, need to save rbuf).
  100.  *
  101.  * Revision 1.15  1997/03/27  19:55:27  pvmsrc
  102.  * Fixed up pvmbeatask() to go get tracer info if spawned from shell:
  103.  *     - env var info including trace mask, trace buffer size, trace opts.
  104.  *     - use PVMTRACERCLASS mbox entry to fill in values, if matches
  105.  *         on trctid, trcctx, and trctag.
  106.  *
  107.  * Revision 1.14  1997/03/07  15:12:11  pvmsrc
  108.  * Fixed annoying SGI warnings for qsort()'s  int_compare() function...
  109.  *
  110.  * Revision 1.13  1997/03/06  21:50:17  pvmsrc
  111.  * Yanked out #includes for <netinet/in.h> and <netinet/tcp.h>.
  112.  *     - dups with lpvm.h #includes...
  113.  *
  114.  * Revision 1.12  1997/03/06  21:06:10  pvmsrc
  115.  * - added include for lmsg.h, host.h
  116.  * - for mpp's added pvmmimd.h, mppmsg.h
  117.  * - moved struct ttpcb definition to header file lpvm.h
  118.  * - for mpps added call to mpp_ttpcb_find inside of ttpcb_find
  119.  * - mxinput rewritten to handle mpp input streams when ifdef'ed on
  120.  * - Added a stack of inplace headers instead of just one dummy header.
  121.  *   so we can do asynch header transmission
  122.  * - in mxfer:
  123.  *     logic written in to handle mpp streams, including bypass of
  124.  *     reading routes if writing, posting a complete message for
  125.  *     asynch send before checking for read routes, pass information
  126.  *     to pvm_node_send (on mpps) about inplace sending so that
  127.  *     pvm_node_send can be optimized for inplace (not optimized yet :-))
  128.  * - in mroute:
  129.  *     direct routing socket setup turned off for MPPs
  130.  * - in pvmbeatask:
  131.  *     call pvm_mpp_beatask for mpps
  132.  *     don't do socket auth dance for mpps (sockets not used)
  133.  * - added routine ogm_complete to test if an outgoing message is
  134.  *      complete (when sent asychronously). Returns TRUE for workstations
  135.  *     since writes are synchronous
  136.  *
  137.  * Revision 1.11  1997/01/28  19:26:21  pvmsrc
  138.  * New Copyright Notice & Authors.
  139.  *
  140.  * Revision 1.10  1996/12/18  22:27:43  pvmsrc
  141.  * Extracted duplicate versions of routines from lpvm/mimd/shmem.c,
  142.  *     inserted into shared lpvmgen.c:
  143.  *     - pvmbailout().
  144.  *     - pvmlogerror().
  145.  *     - vpvmlogprintf(), pvmlogprintf().  (hope these work on MPP & shmem)
  146.  *     - pvmlogperror().
  147.  *
  148.  * Revision 1.9  1996/10/25  13:57:20  pvmsrc
  149.  * Replaced old #includes for protocol headers:
  150.  *     - <pvmsdpro.h>, "ddpro.h", "tdpro.h"
  151.  * With #include of new combined header:
  152.  *     - <pvmproto.h>
  153.  *
  154.  * Revision 1.8  1996/10/24  22:44:31  pvmsrc
  155.  * Modified for New Tracing Facility:
  156.  *     - moved #include "global.h" below other #include's for typing.
  157.  *     - removed extra #include <pvm3.h> in lpvm.c...
  158.  *     - added #include of new "lpvm.h" to replace explicit externs.
  159.  *     - removed common control message handlers from lpvm.c:
  160.  *         * extracted to lpvmgen.c for general usage.
  161.  *         * pvm_tc_noop(), pvm_tc_settmask(), pvm_tc_siblings().
  162.  *         -> lpvmmimd.c & lpvmshmem.c still need remainder of pvmmctl()
  163.  *             replaced with control message handlers.
  164.  *     - arg typing hassles with int_compare() / qsort() exacerbated...
  165.  *     - modified pvmbeatask():
  166.  *         * handle new tracing info, unpack tracing and output collection
  167.  *             parameters into temp storage, and then check for local task
  168.  *             override before applying.
  169.  *         * read in new tracing env vars PVMTRCBUF & PVMTRCOPT.
  170.  *         * install new common message handlers.
  171.  *         * call new tev_init() routine to set up tracing stuff.
  172.  *         * use new Pvmtracer structures (pvmtrc & pvmctrc) to store info.
  173.  *     - removed pvm_getopt() & pvm_setopt() -> moved to common lpvmgen.c.
  174.  *     - removed old tev_begin(), tev_fin() & tev_do_trace() routines.
  175.  *     - updated trace event generation for pvm_getfds(), pvm_start_pvmd(),
  176.  *         pvm_precv(), pvm_psend().
  177.  *
  178.  * Revision 1.7  1996/10/14  19:17:06  pvmsrc
  179.  * Used ARCHFLAG SOCKLENISUINT where socket length is unsigned int
  180.  *
  181.  * Revision 1.6  1996/10/09  21:48:19  pvmsrc
  182.  * Problem:
  183.  * --------
  184.  * The problem was the result of AIX4.2 changing the expected datatype of
  185.  * the XxxxLength parameter in the following system function calls:
  186.  *
  187.  * int bind (Socket, Name, NameLength)
  188.  * int getsockname (Socket, Name, NameLength)
  189.  * int recvfrom (Socket, Buffer, Length, Flags, From, FromLength)
  190.  * int accept (Socket, Address, AddressLength)
  191.  *
  192.  * The compiler warning message generated was:
  193.  *   Function argument assignment between types "unsigned long*" and "int*"
  194.  *   is not allowed.
  195.  *
  196.  * Action:
  197.  * -------
  198.  * In PVM functions where oslen was already declared_
  199.  *     changed declaration from:    int oslen;
  200.  *                   to:    unsigned int oslen;
  201.  *
  202.  * In PVM functions where a local "temporary" variable such as i, j, etc.
  203.  * was used_
  204.  *     added declaration of:        unsigned int oslen;
  205.  *     and then changed to use oslen where necessary.
  206.  *
  207.  * Revision 1.5  1996/10/04  13:17:23  pvmsrc
  208.  *         New context was generated on each spawn. This is bad.
  209.  *
  210.  * Revision 1.4  1996/09/24  15:15:46  pvmsrc
  211.  * Test failure...  fixed.
  212.  *
  213.  * Revision 1.3  1996/09/24  15:12:19  kohl
  214.  * Test check in...
  215.  *
  216.  * Revision 1.2  1996/09/23  23:30:53  pvmsrc
  217.  * Initial Creation - original lpvm.c.
  218.  *
  219.  * Revision 1.32  1995/11/02  16:07:10  manchek
  220.  * added NEEDSENDIAN switch.
  221.  * must declare ptr to sys_errlist const in pvmlogperror for FREEBSD.
  222.  * free replies to control messages in mxfer
  223.  *
  224.  * Revision 1.31  1995/09/06  17:37:24  manchek
  225.  * aargh, forgot pvm_precv
  226.  *
  227.  * Revision 1.30  1995/09/06  17:30:32  manchek
  228.  * pvm_psend returns not implemented instead of bad param for string type
  229.  *
  230.  * Revision 1.29  1995/07/28  16:40:58  manchek
  231.  * wrap HASERRORVARS around errno declarations
  232.  *
  233.  * Revision 1.28  1995/07/28  16:04:05  manchek
  234.  * switch endian includes on flag, not arch name
  235.  *
  236.  * Revision 1.27  1995/07/19  21:43:04  manchek
  237.  * better mxfer logging
  238.  *
  239.  * Revision 1.26  1995/07/19  21:27:49  manchek
  240.  * use pvmnametag to give symbolic message tags
  241.  *
  242.  * Revision 1.25  1995/07/18  16:59:03  manchek
  243.  * added code to generate and check crc on each message (MCHECKSUM)
  244.  *
  245.  * Revision 1.24  1995/07/03  19:05:35  manchek
  246.  * removed POWER4 arch ifdefs
  247.  *
  248.  * Revision 1.23  1995/06/28  18:18:07  manchek
  249.  * do-nothing check_for_exit so one can be in lpvmshmem.c
  250.  *
  251.  * Revision 1.22  1995/06/19  17:35:05  manchek
  252.  * addr sometimes wasn't set in pvm_tc_conreq, causing segfault
  253.  *
  254.  * Revision 1.21  1995/06/12  15:56:14  manchek
  255.  * added PGON partition size support
  256.  *
  257.  * Revision 1.20  1995/06/02  17:19:14  manchek
  258.  * added check in mxfer() for when outgoing route closed during input
  259.  *
  260.  * Revision 1.19  1995/06/01  14:43:54  manchek
  261.  * pvm_start_pvmd ignores INT, QUIT, TSTP signals
  262.  *
  263.  * Revision 1.18  1995/05/30  17:28:08  manchek
  264.  * added ifdefs for SP2MPI arch
  265.  *
  266.  * Revision 1.17  1995/05/17  17:06:54  manchek
  267.  * added PVMTASKDEBUG envar
  268.  *
  269.  * Revision 1.16  1995/05/17  16:16:36  manchek
  270.  * use FDSETISINT.
  271.  * use umbuf_get and put instead of ALLOC.
  272.  * in mksocs, read pvmd sockaddr file only once.
  273.  * in pvmbeatask, read altpid from environment each time.
  274.  * add PvmPollTime and Type, NotImplemented.
  275.  * pvm_start_pvmd reads sockaddr from pvmd instead of sleeping on addr file,
  276.  * sets PVMSOCK envar from return.
  277.  * allows better synchronization, master host overloading.
  278.  *
  279.  * Revision 1.15  1995/02/01  21:08:46  manchek
  280.  * error 4 is now PvmOverflow.
  281.  * connect is retried in case of EINTR
  282.  *
  283.  * Revision 1.14  1994/12/20  16:28:19  manchek
  284.  * added PvmShowTids case to setopt.
  285.  * removed EOF message on pvmd socket close
  286.  *
  287.  * Revision 1.13  1994/10/15  19:07:31  manchek
  288.  * don't use fd_sets when select returns -1; will hang reading.
  289.  * cast message tags for comparison as integers
  290.  *
  291.  * Revision 1.12  1994/09/02  15:23:37  manchek
  292.  * fixed segfaults in setopt when task not connected
  293.  *
  294.  * Revision 1.11  1994/07/18  19:20:18  manchek
  295.  * fix to call write() with max 4096 length for RS6K
  296.  *
  297.  * Revision 1.10  1994/06/21  19:36:23  manchek
  298.  * forgot to ifdef tt_spath
  299.  *
  300.  * Revision 1.9  1994/06/21  18:31:31  manchek
  301.  * connect in mksocs() tries several times before giving up.
  302.  * don't setsockopt() at TCP level on Unix task-task sockets
  303.  *
  304.  * Revision 1.8  1994/06/04  21:44:57  manchek
  305.  * added unix domain sockets
  306.  *
  307.  * Revision 1.7  1994/06/03  20:38:15  manchek
  308.  * version 3.3.0
  309.  *
  310.  * Revision 1.6  1993/11/30  23:50:01  manchek
  311.  * set nodelay and snd, rcv buffer sizes on t-t sockets
  312.  *
  313.  * Revision 1.5  1993/11/30  15:51:30  manchek
  314.  * beatask complains if it can't write d-auth file (fs full?)
  315.  *
  316.  * Revision 1.4  1993/10/04  20:29:05  manchek
  317.  * mksocks() and pvm_start_pvmd() now use pvmdsockfile(), not TDSOCKNAME.
  318.  * made pvm_useruid global for pvmcruft.c
  319.  *
  320.  * Revision 1.3  1993/10/04  19:10:22  manchek
  321.  * mctl() conflicts with mctl(2) - declare static for now
  322.  *
  323.  * Revision 1.2  1993/09/16  21:36:20  manchek
  324.  * pvm_start_pvmd() was freeing the return string from pvmgetpvmd()
  325.  *
  326.  * Revision 1.1  1993/08/30  23:26:48  manchek
  327.  * Initial revision
  328.  *
  329.  */
  330.  
  331. #ifdef WIN32
  332. #include "pvmwin.h"
  333. #include <process.h>
  334. #endif
  335.  
  336. #include <stdio.h>
  337. #ifdef NEEDMENDIAN
  338. #include <machine/endian.h>
  339. #endif
  340. #ifdef NEEDENDIAN
  341. #include <endian.h>
  342. #endif
  343. #ifdef NEEDSENDIAN
  344. #include <sys/endian.h>
  345. #endif
  346.  
  347. #ifndef WIN32
  348. #include <rpc/types.h>
  349. #include <rpc/xdr.h>
  350. #include <sys/socket.h>
  351. #else
  352. #include "..\xdr\types.h"
  353. #include "..\xdr\xdr.h"
  354. #endif
  355.  
  356. #include <pvm3.h>
  357.  
  358. #ifndef NOUNIXDOM
  359. #include <sys/un.h>
  360. #endif
  361. #ifdef NEEDSSELECTH
  362. #include <sys/select.h>
  363. #endif
  364. #include <sys/stat.h>
  365. #include <fcntl.h>
  366. #ifdef    SYSVSTR
  367. #include <string.h>
  368. #define    CINDEX(s,c)    strchr(s,c)
  369. #else
  370. #include <strings.h>
  371. #define    CINDEX(s,c)    index(s,c)
  372. #endif
  373. #include <errno.h>
  374. #include <signal.h>
  375. #include <pvmproto.h>
  376. #include "pvmalloc.h"
  377. #include "pvmfrag.h"
  378. #include "pmsg.h"
  379. #include "listmac.h"
  380. #include "tvdefs.h"
  381. #include "bfunc.h"
  382. #include "lpvm.h"
  383. #include <pvmtev.h>
  384. #include "tevmac.h"
  385. #include "host.h"
  386. #include "waitc.h"
  387. #include "global.h"
  388. #include "lmsg.h"
  389.  
  390. #ifdef IMA_MPP
  391. #include "pvmmimd.h"
  392. #include "mppmsg.h"
  393. #endif 
  394.  
  395.  
  396. #ifndef    max
  397. #define    max(a,b)    ((a)>(b)?(a):(b))
  398. #endif
  399.  
  400. #ifndef    min
  401. #define    min(a,b)    ((a)<(b)?(a):(b))
  402. #endif
  403.  
  404. #ifndef    TTSOCKBUF
  405. #define    TTSOCKBUF    0x8000
  406. #endif
  407.  
  408. #ifdef    NOTMPNAM
  409. #define    TMPNAMFUN(x)    pvmtmpnam(x)
  410. #define    LEN_OF_TMP_NAM    32
  411. char *pvmtmpnam();
  412.  
  413. #else    /*NOTMPNAM*/
  414. #define    TMPNAMFUN(x)    tmpnam(x)
  415. #ifdef    L_tmpnam
  416. #define    LEN_OF_TMP_NAM    L_tmpnam
  417. #else
  418. #define    LEN_OF_TMP_NAM    64
  419. #endif
  420. #endif    /*NOTMPNAM*/
  421.  
  422.  
  423. /***************
  424.  **  Globals  **
  425.  **           **
  426.  ***************/
  427.  
  428. char *getenv();
  429. void hex_inadport __ProtoGlarp__ (( char *, struct sockaddr_in * ));
  430.  
  431. extern char *inadport_decimal();
  432. extern char *inadport_hex();
  433. char *pvmgetpvmd();
  434. char *pvmdsockfile();
  435. char *pvmnametag();
  436. struct pmsg *midtobuf();
  437. struct pmsg *umbuf_new();
  438. char *debug_flags();
  439. struct msgid *pvm_inprecv = (struct msgid *) NULL;
  440.  
  441. #ifndef HASERRORVARS
  442. extern int errno;                        /* from libc */
  443. extern char *sys_errlist[];
  444. extern int sys_nerr;
  445. #endif
  446.  
  447. #if defined(IMA_PGON)
  448. int pvmpgonpartsize = -1;                /* FE prog, no partition */
  449. #endif
  450.  
  451.  
  452. /***************
  453.  **  Private  **
  454.  **           **
  455.  ***************/
  456.  
  457. static int mxfersingle = 1;                /* mxfer returns after single frag */
  458. static struct sockaddr_in pvmourinet;    /* our host ip addr */
  459. static struct ttpcb *ttlist = 0;        /* dll of connected tasks */
  460. static struct ttpcb *topvmd = 0;        /* default route (to pvmd) */
  461. static int pvmnfds = 0;                    /* 1 + highest bit set in fds */
  462. static fd_set pvmrfds;                    /* rd fdset for mxfer() */
  463. static struct pmsg *txlist[100];        /* queue for when mroute reentered */
  464. static int txrp = 0;                    /* txlist read pointer */
  465. static int txwp = 0;                    /* txlist write pointer */
  466. #ifdef WIN32
  467. extern char* username;
  468. int system_loser_win;
  469. #endif
  470.  
  471.  
  472. /**************************
  473.  **  Internal Functions  **
  474.  **                      **
  475.  **************************/
  476.  
  477. int
  478. pvm_fd_add(fd, sets)
  479.     int fd;                /* the fd */
  480.     int sets;            /* which sets */
  481. {
  482. #ifdef    SANITY
  483.     if (fd < 0 || fd >= FD_SETSIZE) {
  484.         pvmlogprintf("pvm_fd_add() bad fd %d\n", fd);
  485.         return 1;
  486.     }
  487. #endif
  488.     if (sets & 1)
  489.         FD_SET(fd, &pvmrfds);
  490. /*
  491.     if (sets & 2)
  492.         FD_SET(fd, &pvmwfds);
  493.     if (sets & 4)
  494.         FD_SET(fd, &pvmefds);
  495. */
  496.  
  497.     /* if this is new highest, adjust nfds */
  498.  
  499.     if (fd >= pvmnfds)
  500.         pvmnfds = fd + 1;
  501.     return 0;
  502. }
  503.  
  504.  
  505. pvm_fd_delete(fd, sets)
  506.     int fd;                /* the fd */
  507.     int sets;            /* which sets */
  508. {
  509. #ifdef    SANITY
  510.     if (fd < 0 || fd >= FD_SETSIZE) {
  511.         pvmlogprintf("pvm_fd_delete() bad fd %d\n", fd);
  512.         return 1;
  513.     }
  514. #endif
  515.     if (sets & 1)
  516.         FD_CLR(fd, &pvmrfds);
  517. /*
  518.     if (sets & 2)
  519.         FD_CLR(fd, &pvmwfds);
  520.     if (sets & 4)
  521.         FD_CLR(fd, &pvmefds);
  522. */
  523.  
  524.     /* if this was highest, may have to adjust nfds to new highest */
  525.  
  526.     if (fd + 1 == pvmnfds)
  527.         while (pvmnfds > 0) {
  528.             pvmnfds--;
  529.             if (FD_ISSET(pvmnfds, &pvmrfds)
  530. /*
  531.             || FD_ISSET(pvmnfds, &pvmefds)
  532.             || FD_ISSET(pvmnfds, &pvmwfds)
  533. */
  534.             ) {
  535.                 pvmnfds++;
  536.                 break;
  537.             }
  538.         }
  539.     return 0;
  540. }
  541.  
  542.  
  543. /*    ttpcb_new()
  544. *
  545. *    Create a new, blank ttpcb.
  546. */
  547.  
  548. struct ttpcb *
  549. ttpcb_new()
  550. {
  551.     struct ttpcb *pcbp;
  552.  
  553.     if (pcbp = TALLOC(1, struct ttpcb, "tpcb")) {
  554.         BZERO((char*)pcbp, sizeof(struct ttpcb));
  555.         pcbp->tt_fd = -1;
  556.         pcbp->tt_rxfrag = pmsg_new(1);
  557.         BZERO((char*)pcbp->tt_rxfrag, sizeof(struct pmsg));
  558.         pcbp->tt_rxfrag->m_link = pcbp->tt_rxfrag->m_rlink = pcbp->tt_rxfrag;
  559.     }
  560.     return pcbp;
  561. }
  562.  
  563.  
  564. /*    ttpcb_delete()
  565. *
  566. *    Get rid of a ttpcb.  Delete it from any list, close the socket,
  567. *    free any rx frag heap.
  568. */
  569.  
  570. void
  571. ttpcb_delete(pcbp)
  572.     struct ttpcb *pcbp;
  573. {
  574.     struct pmsg *up;
  575.  
  576.     if (pcbp->tt_link) {
  577.         LISTDELETE(pcbp, tt_link, tt_rlink);
  578.     }
  579.     if (pcbp->tt_fd != -1) {
  580.         pvm_fd_delete(pcbp->tt_fd, 3);
  581.         (void)close(pcbp->tt_fd);
  582.     }
  583.     if (up = pcbp->tt_rxfrag) {
  584.         while (up->m_link != up)
  585.             umbuf_free(up->m_link);
  586.         pmsg_unref(up);
  587.     }
  588.     if (pcbp->tt_rxf)
  589.         fr_unref(pcbp->tt_rxf);
  590. #ifndef NOUNIXDOM
  591.     if (pcbp->tt_spath)
  592.         (void)unlink(pcbp->tt_spath);
  593. #endif
  594.  
  595.     PVM_FREE(pcbp);
  596. }
  597.  
  598.  
  599. /*    ttpcb_creat()
  600. *
  601. *    Create a new task-task entry.  Allocates a ttpcb, inserts it in
  602. *    ttlist.
  603. */
  604.  
  605. struct ttpcb *
  606. ttpcb_creat(tid)
  607.     int tid;        /* peer tid */
  608. {
  609.     struct ttpcb *pcbp, *pcbp2;
  610.  
  611.     if (pcbp = ttpcb_new()) {
  612.         pcbp->tt_tid = tid;
  613.  
  614.         for (pcbp2 = ttlist->tt_link; pcbp2 != ttlist; pcbp2 = pcbp2->tt_link)
  615.             if (pcbp2->tt_tid > tid)
  616.                 break;
  617.         LISTPUTBEFORE(pcbp2, pcbp, tt_link, tt_rlink);
  618.     }
  619.     return pcbp;
  620. }
  621.  
  622.  
  623. /*    ttpcb_find()
  624. *
  625. *    Find a task-task entry by tid in ttlist.
  626. */
  627.  
  628. struct ttpcb *
  629. ttpcb_find(tid)
  630.     int tid;        /* peer tid */
  631. {
  632.     struct ttpcb *pcbp;
  633.  
  634. #if defined(IMA_MPP)
  635.     if ( pcbp = mpp_ttpcb_find(tid))
  636.         return pcbp;
  637. #endif
  638.     for (pcbp = ttlist->tt_link; pcbp != ttlist; pcbp = pcbp->tt_link)
  639.         if (pcbp->tt_tid >= tid)
  640.             break;
  641.     return (pcbp->tt_tid == tid) ? pcbp : (struct ttpcb*)0;
  642. }
  643.  
  644.  
  645. /*    ttpcb_dead()
  646. *
  647. *    Mark ttpcb dead, close socket, remove it from fd sets.
  648. */
  649.  
  650. void
  651. ttpcb_dead(pcbp)
  652.     struct ttpcb *pcbp;
  653. {
  654.     struct pmsg *up;
  655.     int sbf;
  656.  
  657.     pcbp->tt_state = TTDEAD;
  658.     if (pcbp->tt_fd != -1) {
  659.         pvm_fd_delete(pcbp->tt_fd, 3);
  660.         (void)close(pcbp->tt_fd);
  661.  
  662.     /* notify routing socket closed */
  663.  
  664.     /*
  665.     XXX problems with the route notify messages:
  666.     XXX they can be delayed / cause deadlock because gotem isn't incremented
  667.     */
  668.         check_routedelete(pcbp);
  669.         pcbp->tt_fd = -1;
  670.     }
  671. #ifndef NOUNIXDOM
  672.     if (pcbp->tt_spath) {
  673.         (void)unlink(pcbp->tt_spath);
  674.         pcbp->tt_spath = 0;
  675.     }
  676. #endif
  677.     if (pcbp->tt_rxf) {
  678.         fr_unref(pcbp->tt_rxf);
  679.         pcbp->tt_rxf = 0;
  680.     }
  681.     if (up = pcbp->tt_rxfrag) {
  682.         while (up->m_link != up)
  683.             umbuf_free(up->m_link);
  684.     }
  685. }
  686.  
  687.  
  688. int
  689. ttpcb_dump(pcbp)
  690.     struct ttpcb *pcbp;
  691. {
  692.     pvmlogprintf("ttpcb_dump() t%x fd=%d sad=%s",
  693.         pcbp->tt_tid,
  694.         pcbp->tt_fd,
  695.         inadport_decimal(&pcbp->tt_sad));
  696.     pvmlogprintf(" osad=%s state=%d\n",
  697.         inadport_decimal(&pcbp->tt_osad), pcbp->tt_state);
  698.     return 0;
  699. }
  700.  
  701.  
  702. int
  703. ttpcb_dumpall()
  704. {
  705.     struct ttpcb *pcbp;
  706.  
  707.     pvmlogerror("ttpcb_dumpall()\n");
  708.     ttpcb_dump(topvmd);
  709.     for (pcbp = ttlist->tt_link; pcbp != ttlist; pcbp = pcbp->tt_link)
  710.         ttpcb_dump(pcbp);
  711.     return 0;
  712. }
  713.  
  714.  
  715. /*    check_routeadd()
  716. *
  717. *    Check if a notify is posted for new route creation, and send us
  718. *    a message if so.
  719. */
  720.  
  721. int
  722. check_routeadd(pcbp)
  723.     struct ttpcb *pcbp;
  724. {
  725.     struct waitc *wp, *wp2;
  726.     struct pmsg *up;
  727.     int sbf;
  728.  
  729.     wp = waitlist->wa_link;
  730.     while (wp != waitlist) {
  731.         wp2 = wp->wa_link;
  732.         if (wp->wa_kind == WT_ROUTEA) {
  733.             sbf = pvm_setsbuf(pvm_mkbuf(PvmDataFoo));
  734.             pvm_pkint(&pcbp->tt_tid, 1, 1);
  735.             pvm_pkint(&pcbp->tt_fd, 1, 1);
  736.             sbf = pvm_setsbuf(sbf);
  737.             up = midtobuf(sbf);
  738.             up->m_ctx = wp->wa_mesg->m_ctx;
  739.             up->m_tag = wp->wa_mesg->m_tag;
  740.             mesg_input(up);
  741.             if (wp->wa_count != -1 && --wp->wa_count < 1)
  742.                 wait_delete(wp);
  743.         }
  744.         wp = wp2;
  745.     }
  746.     return 0;
  747. }
  748.  
  749.  
  750. /*    check_routedelete()
  751. *
  752. *    Check if a notify is posted for route deletion, and send us
  753. *    a message if so.
  754. */
  755.  
  756. int
  757. check_routedelete(pcbp)
  758.     struct ttpcb *pcbp;
  759. {
  760.     struct waitc *wp, *wp2;
  761.     struct pmsg *up;
  762.     int tid = pcbp->tt_tid;
  763.  
  764.     wp = waitlist->wa_link;
  765.     while (wp != waitlist) {
  766.         wp2 = wp->wa_link;
  767.         if (wp->wa_kind == WT_ROUTED && tid == wp->wa_on) {
  768.             up = wp->wa_mesg;
  769.             wp->wa_mesg = 0;
  770.             mesg_input(up);
  771.             wait_delete(wp);
  772.         }
  773.         wp = wp2;
  774.     }
  775.     return 0;
  776. }
  777.  
  778.  
  779. int
  780. post_routedelete(tid, ctx, tag)
  781.     int tid;
  782.     int ctx;
  783.     int tag;
  784. {
  785.     int sbf;
  786.     struct waitc *wp;
  787.     struct pmsg *up;
  788.     int i;
  789.  
  790.     sbf = pvm_setsbuf(pvm_mkbuf(PvmDataFoo));
  791.     pvm_pkint(&tid, 1, 1);
  792.     i = -1;
  793.     pvm_pkint(&i, 1, 1);
  794.     sbf = pvm_setsbuf(sbf);
  795.     up = midtobuf(sbf);
  796.     up->m_ctx = ctx;
  797.     up->m_tag = tag;
  798.  
  799.     if (ttpcb_find(tid)) {
  800.         wp = wait_new(WT_ROUTED);
  801.         wp->wa_tid = pvmmytid;
  802.         wp->wa_on = tid;
  803.         wp->wa_mesg = up;
  804.  
  805.     } else {
  806.         mesg_input(up);
  807.     }
  808.     return 0;
  809. }
  810.  
  811.  
  812. /*    pvm_tc_conreq()
  813. *
  814. *    Another task requests a connection with us.
  815. *    Reply with a TC_CONACK message.
  816. *
  817. *    TC_CONREQ() {
  818. *        int tdprotocol        // t-d protocol revision number
  819. *        string sockaddr        // address of other socket
  820. *    }
  821. */
  822.  
  823. static int
  824. pvm_tc_conreq(mid)
  825.     int mid;
  826. {
  827.     int src;                    /* sender of request */
  828.     int rbf;                    /* rx buffer temp */
  829.     int sbf = 0;                /* reply message mid */
  830.     int ttpro;                    /* protocol revision */
  831.     struct ttpcb *pcbp;            /* pcb for connection */
  832.     int ackd;                    /* allow connection (0) */
  833.     char *addr = "";            /* socket address */
  834.     static int linger[2] = { 1, 60 };   /* XXX arbitrary time */
  835.     int i;
  836.     int ictx;
  837. #ifdef SOCKLENISUINT
  838.     size_t oslen;
  839. #else
  840.     int oslen;
  841. #endif
  842. #ifndef NOUNIXDOM
  843.     struct sockaddr_un uns;
  844.     char spath[LEN_OF_TMP_NAM];
  845. #endif
  846.     char buf[256];
  847.  
  848.     rbf = pvm_setrbuf(mid);
  849.     pvm_bufinfo(mid, (int *)0, (int *)0, &src);
  850.  
  851.     pvm_upkint(&ttpro, 1, 1);
  852.     pvm_upkstr(buf);
  853.  
  854.     if (pcbp = ttpcb_find(src)) {
  855.         if (pvmdebmask & PDMROUTE) {
  856.             pvmlogprintf("pvm_tc_conreq() crossed CONREQ from t%x\n", src);
  857.         }
  858.         if (pcbp->tt_state == TTCONWAIT) {
  859.             if (buf[0] == '/') {
  860. #ifdef NOUNIXDOM
  861.                 pvmlogprintf(
  862.                 "pvm_tc_conreq() CONREQ from t%x, Unix domain socket unsupported\n",
  863.                         src);
  864.  
  865. #else /*NOUNIXDOM*/
  866.                 BZERO((char*)&uns, sizeof(uns));
  867.                 uns.sun_family = AF_UNIX;
  868.                 strcpy(uns.sun_path, buf);
  869.                 while ((i = connect(pcbp->tt_fd, (struct sockaddr*)&uns,
  870.                         sizeof(uns))) == -1
  871.                         && errno == EINTR)
  872.                     ;
  873.                 if (i == -1)
  874.                     pvmlogperror("pvm_tc_conreq() connect");
  875.                 else
  876.                     pcbp->tt_state = TTOPEN;
  877. #endif /*NOUNIXDOM*/
  878.  
  879.             } else {
  880.                 pcbp->tt_osad.sin_family = AF_INET;
  881.                 hex_inadport(buf, &pcbp->tt_osad);
  882.                 while ((i = connect(pcbp->tt_fd,
  883.                         (struct sockaddr*)&pcbp->tt_osad,
  884.                         sizeof(pcbp->tt_osad))) == -1
  885.                         && errno == EINTR)
  886.                     ;
  887.                 if (i == -1) {
  888.                     pvmlogperror("pvm_tc_conreq() connect");
  889.  
  890.                 } else {
  891.                     pcbp->tt_state = TTOPEN;
  892. #ifndef NOSOCKOPT
  893.                     if (setsockopt(pcbp->tt_fd, SOL_SOCKET, SO_LINGER,
  894.                             (char*)linger, sizeof(linger)) == -1)
  895.                         pvmlogperror("pvm_tc_conreq() setsockopt");
  896. #endif /*NOSOCKOPT*/
  897.                 }
  898.  
  899.             }
  900.             if (pcbp->tt_state == TTOPEN) {
  901. #ifndef WIN32
  902.                 if ((i = fcntl(pcbp->tt_fd, F_GETFL, 0)) == -1)
  903.                     pvmlogperror("pvm_tc_conreq() fcntl");
  904.                 else {
  905. #ifdef O_NDELAY
  906.                     i |= O_NDELAY;
  907. #else
  908.                     i |= FNDELAY;
  909. #endif
  910.                     (void)fcntl(pcbp->tt_fd, F_SETFL, i);
  911.                 }
  912. #endif
  913.                 pvm_fd_add(pcbp->tt_fd, 1);
  914.             }
  915.  
  916.         } else {
  917.             pvmlogprintf("pvm_tc_conreq() CONREQ from t%x but state=%d ?\n",
  918.                     src, pcbp->tt_state);
  919.         }
  920.  
  921.     } else {
  922.         if (pvmdebmask & PDMROUTE) {
  923.             pvmlogprintf("pvm_tc_conreq() CONREQ from t%x\n", src);
  924.         }
  925.         ackd = 1;
  926.         pcbp = ttpcb_creat(src);
  927.         if (pvmrouteopt != PvmDontRoute) {
  928.             if (buf[0] == '/') {
  929. #ifdef NOUNIXDOM
  930.                 pvmlogprintf(
  931.                 "pvm_tc_conreq() CONREQ from t%x, Unix domain socket unsupported\n",
  932.                         src);
  933.  
  934. #else /*NOUNIXDOM*/
  935.                 if ((pcbp->tt_fd = socket(AF_UNIX, SOCK_STREAM, 0)) == -1) {
  936.                     pvmlogperror("pvm_tc_conreq() socket");
  937.  
  938.                 } else {
  939.                     (void)TMPNAMFUN(spath);
  940.                     BZERO((char*)&uns, sizeof(uns));
  941.                     uns.sun_family = AF_UNIX;
  942.                     spath[0] = 0;
  943.                     (void)tmpnam(spath);
  944.                     strcpy(uns.sun_path, spath);
  945.  
  946.                     if (bind(pcbp->tt_fd, (struct sockaddr*)&uns, sizeof(uns))
  947.                     == -1) {
  948.                         pvmlogperror("pvm_tc_conreq() bind");
  949.  
  950.                     } else {
  951.                         if (listen(pcbp->tt_fd, 1) == -1)
  952.                             pvmlogperror("pvm_tc_conreq() listen");
  953.  
  954.                         else {
  955.                             pcbp->tt_state = TTGRNWAIT;
  956.                             pvm_fd_add(pcbp->tt_fd, 1);
  957.                             ackd = 0;
  958.                             addr = pcbp->tt_spath = STRALLOC(spath);
  959.  
  960.     /* new route socket listening, will be accepted later */
  961.  
  962.                             check_routeadd(pcbp);
  963.                         }
  964.                     }
  965.                 }
  966. #endif /*NOUNIXDOM*/
  967.  
  968.             } else {
  969.                 if ((pcbp->tt_fd = socket(AF_INET, SOCK_STREAM, 0)) == -1) {
  970.                     pvmlogperror("pvm_tc_conreq() socket");
  971.  
  972.                 } else {
  973.                     pcbp->tt_sad = pvmourinet;
  974.                     oslen = sizeof(pcbp->tt_sad);
  975.                     if (bind(pcbp->tt_fd, (struct sockaddr*)&pcbp->tt_sad, oslen) == -1) {
  976.                         pvmlogperror("pvm_tc_conreq() bind");
  977.  
  978.                     } else {
  979.                         if (getsockname(pcbp->tt_fd,
  980.                                 (struct sockaddr*)&pcbp->tt_sad, &oslen) == -1) {
  981.                             pvmlogperror("pvm_tc_conreq() getsockname");
  982.  
  983.                         } else {
  984.                             if (listen(pcbp->tt_fd, 1) == -1)
  985.                                 pvmlogperror("pvm_tc_conreq() listen");
  986.  
  987.                             else {
  988.                                 hex_inadport(buf, &pcbp->tt_osad);
  989.                                 pcbp->tt_state = TTGRNWAIT;
  990.                                 pvm_fd_add(pcbp->tt_fd, 1);
  991.                                 ackd = 0;
  992.                                 addr = inadport_hex(&pcbp->tt_sad);
  993.  
  994.     /* new route socket listening, will be accepted later */
  995.  
  996.                                 check_routeadd(pcbp);
  997.                             }
  998.                         }
  999.                     }
  1000.                 }
  1001.             }
  1002.         }
  1003.  
  1004.         sbf = pvm_setsbuf(pvm_mkbuf(PvmDataFoo));
  1005.         ttpro = TDPROTOCOL;
  1006.         pvm_pkint(&ttpro, 1, 1);
  1007.         pvm_pkint(&ackd, 1, 1);
  1008.         pvm_pkstr(addr);
  1009.         i = pvmrescode;
  1010.         pvmrescode = 1;
  1011.         ictx = pvm_setcontext(SYSCTX_TC);
  1012.         pvm_send(src, TC_CONACK);
  1013.         pvm_setcontext(ictx);
  1014.         pvmrescode = i;
  1015.         pvm_freebuf(pvm_setsbuf(sbf));
  1016.  
  1017.         if (ackd)
  1018.             ttpcb_delete(pcbp);
  1019.     }
  1020.     pvm_setrbuf(rbf);
  1021.     pvm_freebuf(mid);
  1022.     return 0;
  1023. }
  1024.  
  1025.  
  1026. /*    pvm_tc_conack()
  1027. *
  1028. *    Another task replies to our connection request.
  1029. *
  1030. *    TC_CONACK() {
  1031. *        int tdprotocol        // t-d protocol revision number
  1032. *        int ack                // 0 ok, 1 denied
  1033. *        string sockaddr        // address of other socket
  1034. *    }
  1035. */
  1036.  
  1037. static int
  1038. pvm_tc_conack(mid)
  1039.     int mid;
  1040. {
  1041.     int src;                    /* sender of reply */
  1042.     int rbf;                    /* rx buffer temp */
  1043.     int ttpro;                    /* protocol revision */
  1044.     int ackd;                    /* connection allowed (0) */
  1045.     struct ttpcb *pcbp;            /* pcb for connection */
  1046.     static int linger[2] = { 1, 60 };   /* XXX arbitrary time */
  1047.     int i;
  1048. #ifndef NOUNIXDOM
  1049.     struct sockaddr_un uns;
  1050. #endif
  1051.     char buf[256];
  1052.  
  1053.     rbf = pvm_setrbuf(mid);
  1054.     pvm_bufinfo(mid, (int *)0, (int *)0, &src);
  1055.  
  1056.     pvm_upkint(&ttpro, 1, 1);
  1057.     pvm_upkint(&ackd, 1, 1);
  1058.     pvm_upkstr(buf);
  1059.  
  1060.     if (pcbp = ttpcb_find(src)) {
  1061.         if (pcbp->tt_state == TTCONWAIT) {
  1062.             if (pvmdebmask & PDMROUTE) {
  1063.                 pvmlogprintf("pvm_tc_conack() CONACK from t%x\n", src);
  1064.             }
  1065.             if (ttpro != TDPROTOCOL) {
  1066.                 pvmlogprintf("pvm_tc_conack() t-t protocol mismatch with t%x\n",
  1067.                         pcbp->tt_tid);
  1068.                 ackd = 1;
  1069.  
  1070.             } else {
  1071.                 if (ackd != 0) {
  1072.                     if (pvmdebmask & PDMROUTE) {
  1073.                         pvmlogprintf("pvm_tc_conack() route to t%x denied\n",
  1074.                                 pcbp->tt_tid);
  1075.                     }
  1076.  
  1077.                 } else {
  1078.                     if (buf[0] == '/') {
  1079. #ifdef NOUNIXDOM
  1080.                         pvmlogprintf(
  1081.                         "pvm_tc_conack() CONREQ from t%x, Unix domain socket unsupported\n",
  1082.                                 src);
  1083.                         ackd = 1;
  1084. #else /*NOUNIXDOM*/
  1085.                         BZERO((char*)&uns, sizeof(uns));
  1086.                         uns.sun_family = AF_UNIX;
  1087.                         strcpy(uns.sun_path, buf);
  1088.                         while ((i = connect(pcbp->tt_fd, (struct sockaddr*)&uns,
  1089.                                 sizeof(uns))) == -1
  1090.                                 && errno == EINTR)
  1091.                             ;
  1092.                         if (i == -1) {
  1093.                             pvmlogperror("pvm_tc_conack() connect");
  1094.                             ackd = 1;
  1095.  
  1096.                         } else {
  1097.                             pcbp->tt_state = TTOPEN;
  1098. #ifndef WIN32    
  1099.                             if ((i = fcntl(pcbp->tt_fd, F_GETFL, 0)) == -1)
  1100.                                 pvmlogperror("pvm_tc_conack() fcntl");
  1101.                             else {
  1102. #ifdef O_NDELAY
  1103.                                 i |= O_NDELAY;
  1104. #else
  1105.                                 i |= FNDELAY;
  1106. #endif
  1107.                                 (void)fcntl(pcbp->tt_fd, F_SETFL, i);
  1108.                             }
  1109. #endif
  1110.                             pvm_fd_add(pcbp->tt_fd, 1);
  1111.                         }
  1112.  
  1113. #endif /*NOUNIXDOM*/
  1114.  
  1115.                     } else {
  1116.                         pcbp->tt_osad.sin_family = AF_INET;
  1117.                         hex_inadport(buf, &pcbp->tt_osad);
  1118.                         while ((i = connect(pcbp->tt_fd,
  1119.                                 (struct sockaddr*)&pcbp->tt_osad,
  1120.                                 sizeof(pcbp->tt_osad))) == -1
  1121.                                 && errno == EINTR)
  1122.                             ;
  1123.                         if (i == -1) {
  1124.                             pvmlogperror("pvm_tc_conack() connect");
  1125.                             ackd = 1;
  1126.  
  1127.                         } else {
  1128.                             pcbp->tt_state = TTOPEN;
  1129. #ifndef NOSOCKOPT
  1130.                             if (setsockopt(pcbp->tt_fd, SOL_SOCKET, SO_LINGER,
  1131.                                     (char*)linger, sizeof(linger)) == -1)
  1132.                                 pvmlogperror("pvm_tc_conack() setsockopt");
  1133. #endif /*NOSOCKOPT*/
  1134.  
  1135. #ifndef WIN32
  1136.                             if ((i = fcntl(pcbp->tt_fd, F_GETFL, 0)) == -1)
  1137.                                 pvmlogperror("pvm_tc_conack() fcntl");
  1138.                             else {
  1139. #ifdef O_NDELAY
  1140.                                 i |= O_NDELAY;
  1141. #else
  1142.                                 i |= FNDELAY;
  1143. #endif
  1144.                                 (void)fcntl(pcbp->tt_fd, F_SETFL, i);
  1145.                             }
  1146.                             pvm_fd_add(pcbp->tt_fd, 1);
  1147. #endif
  1148.                         }
  1149.                     }
  1150.                 }
  1151.             }
  1152.  
  1153.             if (ackd != 0) {
  1154.                 pcbp->tt_state = TTDENY;
  1155.                 (void)close(pcbp->tt_fd);
  1156.                 pcbp->tt_fd = -1;
  1157.             }
  1158.  
  1159.         } else {
  1160.             pvmlogprintf("pvm_tc_conack() CONACK from t%x but state=%d\n",
  1161.                     src, pcbp->tt_state);
  1162.         }
  1163.  
  1164.     } else {
  1165.         pvmlogprintf("pvm_tc_conack() suprious CONACK from t%x\n", src);
  1166.     }
  1167.  
  1168.     pvm_setrbuf(rbf);
  1169.     pvm_freebuf(mid);
  1170.     return 0;
  1171. }
  1172.  
  1173.  
  1174. /*    pvm_tc_taskexit()
  1175. *
  1176. *    We are notified that another task (to which we have a direct route)
  1177. *    has exited.
  1178. */
  1179.  
  1180. static int
  1181. pvm_tc_taskexit(mid)
  1182.     int mid;
  1183. {
  1184.     int rbf;                    /* rx buffer temp */
  1185.     int tid;                    /* exited task id */
  1186.     struct ttpcb *pcbp;
  1187.  
  1188.     rbf = pvm_setrbuf(mid);
  1189.  
  1190.     pvm_upkint(&tid, 1, 1);
  1191.  
  1192.     if (pvmdebmask & PDMROUTE) {
  1193.         pvmlogprintf("pvm_tc_taskexit() TASKEXIT for t%x\n", tid);
  1194.     }
  1195.  
  1196.     /*
  1197.     * v3.3: for now, don't close fully open route as we may lose
  1198.     * messages.  rely on socket getting EOF
  1199.     */
  1200.     if ((pcbp = ttpcb_find(tid))
  1201.     && pcbp->tt_state != TTOPEN)
  1202.         ttpcb_dead(pcbp);
  1203.  
  1204.     pvm_setrbuf(rbf);
  1205.     pvm_freebuf(mid);
  1206.     return 0;
  1207. }
  1208.  
  1209.  
  1210. /*    mxinput()
  1211. *
  1212. *    Input from a connection.
  1213. *    Reassemble packets into messages and receive them.
  1214. *    Returns >= 0 the number of messages added to pvmrxlist,
  1215. *    or negative on error.
  1216. */
  1217.  
  1218. static int
  1219. mxinput(pcbp)
  1220.     struct ttpcb *pcbp;
  1221.  
  1222. {
  1223.     int gotem = 0;            /* num msgs added to pvmrxlist */
  1224.     struct frag *fp;        /* shadows pcbp->tt_rxf */
  1225.     struct frag *fp2;
  1226.     int n;                    /* bytes received */
  1227.     int m;                    /* length of fragment */
  1228.     struct pmsg *rxup;        /* message containing this frag */
  1229.     struct pmsg *frgpile, *hdfrgpile;
  1230.     char *cp;                /* gp */
  1231.     int src;
  1232.     int dst;
  1233.     int ff;
  1234.     static int fairprobe = 0;
  1235.  
  1236.  
  1237. #if defined(IMA_MPP)
  1238.  
  1239.     /* Messages from Tasks and  Messages from the daemon  are probed
  1240.      * fairprobe makes sure that neither interface gets starved.  
  1241.      * fairprobe is toggled when an EOM is found  
  1242.     */
  1243.  
  1244.     switch (fairprobe)
  1245.     {
  1246.         /* pvm_readfrom<xxxx> returns a pointer to a frag, with its
  1247.          *    length properly filled in. cp returns a pointer to the
  1248.          *    the start of the data
  1249.         */
  1250.         case 0:
  1251.             if ((fp = pvm_readfrompeer()) == (struct frag *) NULL) 
  1252.                 fp = pvm_readfrompvmd();
  1253.             break;
  1254.         
  1255.         default:    
  1256.             if ((fp = pvm_readfrompvmd()) == (struct frag *) NULL) 
  1257.                 fp = pvm_readfrompeer();
  1258.             break;
  1259.  
  1260.     }
  1261.  
  1262.     if (!fp) 
  1263.         return gotem;    /* didn't read anything */
  1264.  
  1265. #else
  1266.     if (!pcbp->tt_rxf)
  1267.         if (!(pcbp->tt_rxf = fr_new(pvmfrgsiz)))
  1268.             return PvmNoMem;
  1269.     fp = pcbp->tt_rxf;
  1270.  
  1271.     /* read fragment header separately from body */
  1272.  
  1273.     n = (fp->fr_len < TDFRAGHDR) ? 0 : pvmget32(fp->fr_dat + 8);
  1274.     n += TDFRAGHDR - fp->fr_len;
  1275.     if (pvmdebmask & PDMPACKET) {
  1276.         pvmlogprintf("mxinput() pcb t%x fr_len=%d fr_dat=+%d n=%d\n",
  1277.                 pcbp->tt_tid, fp->fr_len, fp->fr_dat - fp->fr_buf, n);
  1278.     }
  1279. #ifndef WIN32
  1280.     n = read(pcbp->tt_fd, fp->fr_dat + fp->fr_len, n);
  1281. #else
  1282.     n = win32_read_socket( pcbp->tt_fd,fp->fr_dat+fp->fr_len,n);
  1283. #endif
  1284.     if (pvmdebmask & PDMPACKET) {
  1285.         pvmlogprintf("mxinput() read=%d\n", n);
  1286.     }
  1287.  
  1288.     /* deal with errors and closes */
  1289.  
  1290.     if (n == -1 && 
  1291. #ifndef WIN32
  1292.             errno != EWOULDBLOCK && 
  1293. #endif 
  1294.             errno != EINTR)
  1295.     {
  1296.         if (pvmdebmask & PDMPACKET) {
  1297.             pvmlogperror("mxinput() read");
  1298.             pvmlogprintf("mxinput() t%x\n", pcbp->tt_tid);
  1299.         }
  1300.         return PvmSysErr;
  1301.     }
  1302.     if (!n) {
  1303.         if (pvmdebmask & PDMPACKET) {
  1304.             pvmlogprintf("mxinput() t%x read EOF\n", pcbp->tt_tid);
  1305.         }
  1306.         return -1;
  1307.     }
  1308.  
  1309.     if (n < 1)
  1310.         return gotem;
  1311.     if ((fp->fr_len += n) < TDFRAGHDR)
  1312.         return gotem;
  1313.  
  1314.     /* realloc buffer if frag won't fit */
  1315.  
  1316.     m = TDFRAGHDR + pvmget32(fp->fr_dat + 8);
  1317.     if (fp->fr_len == TDFRAGHDR) {
  1318.         if (m > fp->fr_max - (fp->fr_dat - fp->fr_buf)) {
  1319.             fp2 = fr_new(m);
  1320.             BCOPY(fp->fr_dat, fp2->fr_dat, TDFRAGHDR);
  1321.             fp2->fr_len = fp->fr_len;
  1322.             fr_unref(fp);
  1323.             fp = pcbp->tt_rxf = fp2;
  1324.             if (pvmdebmask & PDMPACKET) {
  1325.                 pvmlogprintf("mxinput() realloc frag max=%d\n", m);
  1326.             }
  1327.         }
  1328.     }
  1329.  
  1330. #endif /* defined (IMA_MPP) */
  1331.     
  1332.     /* Now get information from the frag header to determine
  1333.      * src, destination, length, etc.
  1334.     */
  1335. #if !defined(IMA_MPP)
  1336.     if (fp->fr_len == m) 
  1337. #else
  1338.     if (fp)  /* got a frag */
  1339. #endif
  1340.     {
  1341. #if !defined (IMA_MPP)
  1342.         pcbp->tt_rxf = 0;
  1343. #endif
  1344.         cp = fp->fr_dat;
  1345.         dst = pvmget32(cp);
  1346.         src = pvmget32(cp + 4);
  1347.         ff = pvmget8(cp + 12);
  1348.         fp->fr_len -= TDFRAGHDR;
  1349.         fp->fr_dat += TDFRAGHDR;
  1350.  
  1351.         if (pvmdebmask & PDMPACKET) {
  1352.             pvmlogprintf("mxinput() pkt src t%x len %d ff %d\n",
  1353.                     src, fp->fr_len, ff);
  1354.     }
  1355.  
  1356. #if defined(IMA_MPP)
  1357.     if (fp -> fr_rip )    /* frag was received inplace */
  1358.     {
  1359.         gotem++;
  1360.         fr_unref(fp); /* free frag -- mppprecv knows that the msg completed */
  1361.         return gotem;
  1362.     }
  1363.  
  1364.     frgpile = hdfrgpile = pvm_mpp_pmsgs();
  1365. #else
  1366.     frgpile = hdfrgpile = pcbp->tt_rxfrag ;
  1367. #endif
  1368.     /*
  1369.     * if start of message, make new umbuf, add to frag pile
  1370.     */
  1371.         if (ff & FFSOM) {
  1372.             cp += TDFRAGHDR;
  1373.             fp->fr_len -= MSGHDRLEN;
  1374.             fp->fr_dat += MSGHDRLEN;
  1375.             rxup = umbuf_new();
  1376.             rxup->m_enc = pvmget32(cp);
  1377.             rxup->m_tag = pvmget32(cp + 4);
  1378.             rxup->m_ctx = pvmget32(cp + 8);
  1379.             rxup->m_wid = pvmget32(cp + 16);
  1380.             rxup->m_crc = pvmget32(cp + 20);
  1381.             rxup->m_src = src;
  1382.             rxup->m_dst = dst;
  1383.  
  1384.             LISTPUTBEFORE(hdfrgpile, rxup, m_link, m_rlink);
  1385.  
  1386.         } else {
  1387.             /* locate frag's message */
  1388.  
  1389.             for (rxup = hdfrgpile->m_link; rxup != hdfrgpile; 
  1390.                     rxup = rxup->m_link)
  1391.                 if (rxup->m_src == src)
  1392.                     break;
  1393.         }
  1394.  
  1395.         if (rxup == hdfrgpile) {    /* uh oh, no message for it */
  1396.             pvmlogerror("mxinput() frag with no message\n");
  1397.             fr_unref(fp);
  1398.  
  1399.         } else {
  1400.             LISTPUTBEFORE(rxup->m_frag, fp, fr_link, fr_rlink);
  1401.             rxup->m_len += fp->fr_len;
  1402.     /*
  1403.     * if end of message, move to pvmrxlist and count it
  1404.     */
  1405.             if (ff & FFEOM) {
  1406. #if defined(IMA_MPP)
  1407.                 fairprobe = (fairprobe ? 0 : 1);
  1408. #endif
  1409.                 LISTDELETE(rxup, m_link, m_rlink);
  1410.                 if (pvmdebmask & PDMMESSAGE) {
  1411.                     pvmlogprintf(
  1412.                             "mxinput() src t%x route t%x ctx %d tag %s len %d\n",
  1413.                             rxup->m_src, (pcbp != 0 ? pcbp->tt_tid: -1), 
  1414.                             rxup->m_ctx,
  1415.                             pvmnametag(rxup->m_tag, (int *)0), rxup->m_len);
  1416.                 }
  1417. #ifdef    MCHECKSUM
  1418.                 if (rxup->m_crc != umbuf_crc(rxup)) {
  1419.                     pvmlogprintf(
  1420.                     "mxinput() message src t%x route t%x tag %s bad checksum\n",
  1421.                             rxup->m_src, pcbp->tt_tid,
  1422.                             pvmnametag(rxup->m_tag, (int *)0));
  1423.                     umbuf_free(rxup);
  1424.  
  1425.                 } else {
  1426. #endif
  1427.                     pmsg_setenc(rxup, rxup->m_enc);
  1428.                     mesg_input(rxup);
  1429.                     gotem++;
  1430. #ifdef    MCHECKSUM
  1431.                 }
  1432. #endif
  1433.             }
  1434.         }
  1435.     }
  1436.     return gotem;
  1437. }
  1438.  
  1439.  
  1440. /*    mxfer()
  1441. *
  1442. *    Move message frags between task and pvmd or other tasks.
  1443. *    Returns when
  1444. *        Outgoing message (if any) fully sent AND
  1445. *        (Timed out (tmout) OR
  1446. *            At least one message fully received) AND
  1447. *        No message from pvmd partially received.
  1448. *    Returns >= 0 the number of complete messages downloaded, or
  1449. *    negative on error.
  1450. */
  1451.  
  1452. /* define a preallocated pool of inplace headers */
  1453. #define SHORT_PAYLOAD 128
  1454. #define HEADER_SIZE (TDFRAGHDR + MSGHDRLEN)
  1455. #define NINPLACE_HDRS (8096/(SHORT_PAYLOAD + HEADER_SIZE)) 
  1456. static char inPlaceHdrPool[NINPLACE_HDRS * ( HEADER_SIZE )];
  1457. static int hdrPoolStk = 0;
  1458.  
  1459. static int
  1460. mxfer(txup, tmout)
  1461.     struct pmsg *txup;            /* outgoing message or null */
  1462.     struct timeval *tmout;        /* time limit to get at least one message */
  1463. {
  1464.     struct ttpcb *txpcbp = 0;    /* route for ogm */
  1465.     struct frag *txfp = 0;        /* cur ogm frag or null */
  1466.     struct timeval tin;
  1467.     struct timeval tnow;
  1468.     struct timeval *tvp;
  1469.     fd_set rfds, wfds;
  1470.     int wantmore = 1;            /* nothing rxd yet and not timed out */
  1471.     int gotem = 0;                /* count of received msgs downloaded */
  1472.     int ff;
  1473.     int n;
  1474. #ifdef SOCKLENISUINT
  1475.     size_t oslen;
  1476. #else
  1477.     int oslen;
  1478. #endif
  1479.     char *txcp = 0;                /* point to remainder of txfp */
  1480.     int txtogo = 0;                /* len of remainder of txfp */
  1481.     struct sockaddr_in sad;
  1482.     int s;
  1483.     struct ttpcb *pcbp;
  1484.     char *inPlaceHeader = (char  *) NULL;    /* for inplace data */
  1485.     int inPlaceBodyLen = 0;                    /* len of inplace body */    
  1486.     int bypassRead = FALSE;                /* bypass reading packets before send?*/
  1487.     int waitForOgmToComplete = FALSE;
  1488.     int probedForIncomingPkts = FALSE;    /* need to probe for incoming pkts */ 
  1489.     struct msgid *sendmsg = (struct msgid *) NULL;
  1490.     char errtxt[64];
  1491.  
  1492.     if (tmout)
  1493.         pvmgetclock(&tin);
  1494.  
  1495.     if (txup) {    /* transmitting a umsg */
  1496.         txfp = txup->m_frag->fr_link;
  1497.         if (!txfp->fr_buf) {
  1498.             if (!(txfp = fr_new(MAXHDR)))
  1499.                 return PvmNoMem;
  1500.             txfp->fr_dat += MAXHDR;
  1501.             LISTPUTBEFORE(txup->m_frag, txfp, fr_link, fr_rlink);
  1502.         }
  1503.         /* Get connection info for this dest. If none, go to pvmd */
  1504.         if (!(txpcbp = ttpcb_find(txup->m_dst)) || txpcbp->tt_state != TTOPEN)
  1505.             txpcbp = topvmd;
  1506.         txup->m_ref++;
  1507.         bypassRead = TRUE;        /* bypass reading the first time through */
  1508.     }
  1509.  
  1510.     if (pvmdebmask & PDMMESSAGE) {
  1511.         pvmlogprintf("mxfer() mid %d", (txup ? txup->m_mid : 0));
  1512.         if (txup)
  1513.             pvmlogprintf(" ctx %d tag %s dst t%x route t%x",
  1514.                     txup->m_ctx,
  1515.                     pvmnametag(txup->m_tag, (int *)0),
  1516.                     txup->m_dst, txpcbp->tt_tid);
  1517.         if (tmout)
  1518.             pvmlogprintf(" tmout %d.%06d\n",
  1519.                     tmout->tv_sec, tmout->tv_usec);
  1520.         else
  1521.             pvmlogprintf(" tmout inf\n");
  1522.     }
  1523.  
  1524. /* XXX we go an extra time through select because wantmore gets set
  1525.    XXX inside loop.  no big deal.  also, could avoid calling gettimeofday
  1526.    XXX if tmout is 0.0 */
  1527.  
  1528.     /* Do this loop if
  1529.      *        1) Sending a frag
  1530.      * OR    2) Received *part* of an incoming frag from the daemon
  1531.      * OR    3) Wantmore is true
  1532.      * OR     4) Need the current OGM to complete its asynch send 
  1533.      * OR   5) We haven't probed at least once for incoming packets
  1534.      *
  1535.      * wantmore is initialized to  TRUE  -> loop exec'ed at least once 
  1536.     */
  1537.  
  1538.  
  1539.     while (txfp || topvmd->tt_rxf || wantmore || waitForOgmToComplete
  1540.             || !probedForIncomingPkts
  1541.     ) 
  1542.     {
  1543.  
  1544.         /* Either we are sending something, or have a partial recv'd frag */
  1545.         if (txfp || topvmd->tt_rxf)             /* gotta block */
  1546.         {
  1547.               /* must block if sending any message, or receiving from pvmd */
  1548.             tvp = (struct timeval *) NULL;
  1549.  
  1550.         } 
  1551.         else 
  1552.         {
  1553.             if (wantmore) 
  1554.             {
  1555.                 /* Calculate how long to wait inside the "select"
  1556.                  *    tval = NULL means wait forever
  1557.                  *  tval = (0,0) means probe
  1558.                  *     tval = (x,y) means wait at most x sec + y usec
  1559.                 */
  1560.  
  1561.                 if (tmout)                     /* finite time to block */
  1562.                 {
  1563.                     pvmgetclock(&tnow);
  1564.                     TVXSUBY(&tnow, &tnow, &tin);
  1565.                     if (TVXLTY(tmout, &tnow))     /* time's up */
  1566.                     {
  1567.                         TVCLEAR(&tnow);
  1568.                         wantmore = 0;
  1569.                     } 
  1570.                     else 
  1571.                     {
  1572.                         TVXSUBY(&tnow, tmout, &tnow);
  1573.                     }
  1574.                     tvp = &tnow;
  1575.                 } 
  1576.                 else 
  1577.                 {                        /* forever to block */
  1578.                     tvp = (struct timeval *) NULL;
  1579.                 }
  1580.  
  1581.             } 
  1582.             else 
  1583.             {                            /* return asap */
  1584.                 TVCLEAR(&tnow);
  1585.                 tvp = &tnow;
  1586.             }
  1587.         }
  1588.  
  1589.         /* Here we are setting the read and write file descriptors for
  1590.          *    the following select statement. 
  1591.         */
  1592.  
  1593.  
  1594. #if !defined(IMA_MPP)
  1595.         rfds = pvmrfds;
  1596.         FD_ZERO(&wfds);
  1597.         if (txfp)
  1598.             FD_SET(txpcbp->tt_fd, &wfds);
  1599. #endif
  1600.  
  1601.         if (pvmdebmask & PDMSELECT) {
  1602.             if (tvp)
  1603.                 pvmlogprintf("mxfer() select timeout %d.%06d\n",
  1604.                         tvp->tv_sec, tvp->tv_usec);
  1605.             else
  1606.                 pvmlogprintf("mxfer() select timeout inf\n");
  1607. #if !defined(IMA_MPP)
  1608.             print_fdset("mxfer() rfds=", pvmnfds, &rfds);
  1609.             print_fdset("mxfer() wfds=", pvmnfds, &wfds);
  1610. #endif
  1611.         }
  1612.  
  1613. #if !defined(IMA_MPP)
  1614.         probedForIncomingPkts = TRUE;
  1615.         if ((n = select(pvmnfds,
  1616. #ifdef    FDSETISINT
  1617.                 (int *)&rfds, (int *)&wfds, (int *)0,
  1618. #else
  1619.                 &rfds, &wfds, (fd_set*)0,
  1620. #endif
  1621.                 tvp)) == -1
  1622.         && errno != EINTR) {
  1623.             pvmlogperror("mxfer() select");
  1624.             return PvmSysErr;
  1625.         }
  1626.         if (pvmdebmask & PDMSELECT) {
  1627.             pvmlogprintf("mxfer() select returns %d\n", n);
  1628.         }
  1629.         if (n == -1)
  1630.             continue;
  1631.     /*
  1632.     * if pvmd conn has data ready, read packets
  1633.     */
  1634.  
  1635.         if (FD_ISSET(topvmd->tt_fd, &rfds) 
  1636.             && !(mxfersingle && gotem)) 
  1637.         {
  1638.             if ((n = mxinput(topvmd)) < 0) {
  1639.                 if (n != -1)
  1640.                     pvmlogerror("mxfer() mxinput bad return on pvmd sock\n");
  1641.                 else if (pvmdebmask & (PDMSELECT|PDMMESSAGE|PDMPACKET))
  1642.                     pvmlogerror("mxfer() EOF on pvmd sock\n");
  1643.                 return PvmSysErr;
  1644.             }
  1645.  
  1646.             if (gotem += n)
  1647.                 wantmore = 0;
  1648.         }
  1649.  
  1650.     /*
  1651.     * if task conn has data ready, read packets
  1652.     */
  1653.  
  1654.     /* This goes through *all* of the pcbs that have been defined to
  1655.      *    check for messages.  This is too much overhead for IMA_MPP
  1656.      *    machines. Instead all local routes must be probed at one time.
  1657.     */ 
  1658.         
  1659.         for (pcbp = ttlist->tt_link; pcbp != ttlist; pcbp = pcbp->tt_link) {
  1660.             if (pcbp->tt_state == TTOPEN && FD_ISSET(pcbp->tt_fd, &rfds)) {
  1661.                 if ((n = mxinput(pcbp)) < 0)
  1662.                     ttpcb_dead(pcbp);
  1663.  
  1664.                 else {
  1665.                     if (gotem += n)
  1666.                         wantmore = 0;
  1667.                 }
  1668.  
  1669.             } else /* Try and complete a direct (socket) Connection rqst */ 
  1670.                 if (pcbp->tt_state == TTGRNWAIT
  1671.                 && FD_ISSET(pcbp->tt_fd, &rfds)) {
  1672.                     oslen = sizeof(sad);
  1673.                     s = accept(pcbp->tt_fd, (struct sockaddr*)&sad, &oslen);
  1674.                     if (s == -1) {
  1675.                         pvmlogperror("mxfer() accept");
  1676.                         ttpcb_dead(pcbp);
  1677.  
  1678.                     } else {
  1679. #ifndef NOSOCKOPT
  1680. #ifndef NOUNIXDOM
  1681.                         if (!pcbp->tt_spath) {    /* not unix sock */
  1682. #endif
  1683.                             n = 1;
  1684.                             if (setsockopt(s, IPPROTO_TCP, TCP_NODELAY,
  1685.                                     (char*)&n, sizeof(int)) == -1)
  1686.                                 pvmlogperror("mxfer() setsockopt");
  1687.                             n = TTSOCKBUF;
  1688.                             if (setsockopt(s, SOL_SOCKET, SO_SNDBUF,
  1689.                                     (char*)&n, sizeof(int)) == -1
  1690.                             || setsockopt(s, SOL_SOCKET, SO_RCVBUF,
  1691.                                     (char*)&n, sizeof(n)) == -1)
  1692.                                 pvmlogperror("mxfer() setsockopt SO_SNDBUF");
  1693. #ifndef NOUNIXDOM
  1694.                         }
  1695. #endif
  1696. #endif /*NOSOCKOPT*/
  1697.                         if (pvmdebmask & PDMROUTE) {
  1698.                             pvmlogprintf("mxfer() accept from t%x = %d\n",
  1699.                                     pcbp->tt_tid, s);
  1700.                         }
  1701.                         (void)close(pcbp->tt_fd);
  1702. /*
  1703.                         (void)dup2(s, pcbp->tt_fd);
  1704.                         (void)close(s);
  1705. */
  1706.                         pvm_fd_delete(pcbp->tt_fd, 1);
  1707.  
  1708.     /* notify route socket closed */
  1709.  
  1710.                         check_routedelete(pcbp);
  1711.                         pcbp->tt_fd = s;
  1712.                         pcbp->tt_state = TTOPEN;
  1713.                         pvm_fd_add(s, 1);
  1714.  
  1715.     /* new route socket created for communication */
  1716.  
  1717.                         check_routeadd(pcbp);
  1718.                     }
  1719.                 }
  1720.         }
  1721.  
  1722. #else    /* !IMA_MPP */
  1723.  
  1724.         /* For Native Messaging mxinput is used to probe pvmd AND tasks when 
  1725.          * given a NULL ttpcb pointer 
  1726.         */
  1727.  
  1728.         if (!bypassRead)
  1729.         {
  1730.     
  1731.             probedForIncomingPkts = TRUE;
  1732.             if ((n = mxinput((struct ttpcb *) NULL)) < 0) {
  1733.                     pvmlogerror("mxfer() mxinput bad return on probe\n");
  1734.                     return PvmSysErr;
  1735.                 }
  1736.  
  1737.             if (gotem += n)
  1738.                 wantmore = 0;
  1739.         }
  1740.         
  1741.  
  1742. #endif /* !IMA_MPP */
  1743.     /*
  1744.     * if sending and socket ready to write, send packets
  1745.     */
  1746.  
  1747. #if !defined(IMA_MPP)
  1748.         /* XXX Native message direct routes are alway open, if they exist */
  1749.  
  1750.         if (txfp && txpcbp->tt_state != TTOPEN) 
  1751.         {
  1752.         /* make sure our route hasn't just been closed */
  1753.             txpcbp = topvmd;
  1754.             txcp = 0;
  1755.             txtogo = 0;
  1756.             txfp = txup->m_frag->fr_link;
  1757.  
  1758.         } 
  1759.         else 
  1760. #endif
  1761.         {
  1762.             if (txfp 
  1763.                 && !waitForOgmToComplete
  1764. #if !defined(IMA_MPP)
  1765.                 && FD_ISSET(txpcbp->tt_fd, &wfds) 
  1766. #endif
  1767.             ){
  1768.                 inPlaceHeader = (char *) NULL;         /*sending inplace header ?*/
  1769.                 inPlaceBodyLen = 0;       /* length of inplace body, if inplace*/
  1770.  
  1771.                 if (!txtogo)  /* We haven't sent anything, yet, Build Header */
  1772.                 {
  1773.                     if (txfp->fr_u.dab)            /* packed data */
  1774.                     {
  1775.                         txcp = txfp->fr_dat;
  1776.                     }
  1777.                     else                        /* inplace data */
  1778.                     {
  1779.                         txcp = inPlaceHeader = inPlaceHdrPool + 
  1780.                                 hdrPoolStk*(HEADER_SIZE+SHORT_PAYLOAD) + HEADER_SIZE; 
  1781.                                     
  1782.                         if (pvmdebmask & PDMPACKET)
  1783.                         {
  1784.                             sprintf(errtxt,"mxfer() hdrPoolStk is %d\n", hdrPoolStk);
  1785.                             pvmlogerror(errtxt);
  1786.                         }
  1787.  
  1788.                         if (hdrPoolStk++ >= NINPLACE_HDRS)
  1789.                         {
  1790.                             sprintf(errtxt, "mxfer(): > %d inplace frags \n",
  1791.                                     NINPLACE_HDRS);
  1792.                             pvmlogerror(errtxt);
  1793.                             return PvmSysErr;
  1794.                         }
  1795.  
  1796.                     }
  1797.  
  1798.                     txtogo = txfp->fr_len;
  1799.  
  1800.                     /*
  1801.                       * if this is first frag, prepend message header
  1802.                     */
  1803.                     ff = 0;
  1804.                     if (txfp->fr_rlink == txup->m_frag) 
  1805.                     {
  1806.                         txcp -= MSGHDRLEN;
  1807.                         txtogo += MSGHDRLEN;
  1808.                         pvmput32(txcp,
  1809.                             (txup->m_enc == 0x20000000 ? pvmmydsig : txup->m_enc));
  1810.                         pvmput32(txcp + 4, txup->m_tag);
  1811.                         pvmput32(txcp + 8, txup->m_ctx);
  1812.                         pvmput32(txcp + 16, txup->m_wid);
  1813. #ifdef    MCHECKSUM
  1814.                         pvmput32(txcp + 20, umbuf_crc(txup));
  1815. #else
  1816.                         pvmput32(txcp + 20, 0);
  1817. #endif
  1818.                         ff = FFSOM;
  1819.                     }
  1820.                     if (txfp->fr_link == txup->m_frag)
  1821.                         ff |= FFEOM;
  1822.                     /*
  1823.                      * prepend frag header
  1824.                     */
  1825.                     txcp -= TDFRAGHDR;
  1826.                     pvmput32(txcp, txup->m_dst);
  1827.                     pvmput32(txcp + 4, pvmmytid);
  1828.                     pvmput32(txcp + 8, txtogo);
  1829.                     pvmput32(txcp + 12, 0);        /* to keep putrify happy */
  1830.                     pvmput8(txcp + 12, ff);
  1831.                     txtogo += TDFRAGHDR;
  1832.                     if (!txfp->fr_u.dab)            /* inplace data */
  1833.                     {
  1834.                         txtogo -= txfp->fr_len;
  1835.                         inPlaceBodyLen = txfp->fr_len;
  1836.                     }
  1837.                 }
  1838.  
  1839.                 if (pvmdebmask & PDMPACKET) 
  1840.                 {
  1841.                     pvmlogprintf("mxfer() dst t%x n=%d\n", txup->m_dst, txtogo);
  1842.                 }
  1843.                 
  1844. #if defined(IMA_MPP)
  1845.  
  1846.                 /* node_send will do an async send. Feed it a midlist struct. 
  1847.                  * when we get to the end of a message we call ogm_done
  1848.                  * to make sure message is really gone, and we can free    
  1849.                  * memory 
  1850.                  *    
  1851.                 */
  1852.                 n = pvm_node_send(txcp, txtogo, txpcbp, &sendmsg, 
  1853.                             inPlaceHeader, inPlaceBodyLen);
  1854. #else 
  1855.  
  1856. #if defined(IMA_RS6K) || defined(IMA_SP2MPI)
  1857.                 n = write(txpcbp->tt_fd, txcp, min(txtogo, 4096));
  1858. #else
  1859. #ifndef WIN32
  1860.                 n = write(txpcbp->tt_fd, txcp, txtogo);
  1861. #else 
  1862.                 n = win32_write_socket(txpcbp->tt_fd,txcp,txtogo);
  1863. #endif
  1864. #endif
  1865.  
  1866. #endif
  1867.                 if (pvmdebmask & PDMPACKET) {
  1868.                     pvmlogprintf("mxfer() wrote %d\n", n);
  1869.                 }
  1870.                 if (n == -1 && 
  1871. #ifndef WIN32
  1872.                         errno != EWOULDBLOCK && 
  1873. #endif
  1874.                         errno != EINTR) 
  1875.                 {
  1876.                     if (txpcbp == topvmd) 
  1877.                     {
  1878.                         pvmlogperror("mxfer() write pvmd sock");
  1879.                         return PvmSysErr;
  1880.                     } 
  1881.                     else 
  1882.                     {
  1883.                         pvmlogperror("mxfer() write tt sock");
  1884.                         /* reset message and route to pvmd */
  1885.                         ttpcb_dead(txpcbp);
  1886.                         txpcbp = topvmd;
  1887.                         txcp = 0;
  1888.                         txtogo = 0;
  1889.                         txfp = txup->m_frag->fr_link;
  1890.                     }
  1891.                 }
  1892.  
  1893.                 if (n > 0) 
  1894.                 {
  1895.                     txcp += n;
  1896.                     if ((txtogo -= n) <= 0) 
  1897.                     {
  1898.                         if (txcp == inPlaceHeader && txfp->fr_len )     
  1899.                         /* inplace, body length > 0  */
  1900.                         {
  1901.                             txcp = txfp->fr_dat;
  1902.                             txtogo = txfp->fr_len;
  1903.                             bypassRead = TRUE; /* try to send body without 
  1904.                                                     doing another read */ 
  1905.                         }
  1906.                         else                        /* packed */ 
  1907.                         {
  1908.                             txcp = 0;
  1909.                             txfp = txfp->fr_link;
  1910.                             if (!txfp->fr_buf) {
  1911.                                 txfp = 0;
  1912.                                 waitForOgmToComplete = TRUE;
  1913.                                 bypassRead = FALSE;
  1914.                             }
  1915.                         }
  1916.                     }
  1917.                 } 
  1918.                 else /* we couldn't send, might be a head-head send so ... */ 
  1919.                 {
  1920.                     bypassRead = FALSE; /* enable reading if couldn't send */
  1921.                 }
  1922.             }
  1923.  
  1924.         }
  1925.  
  1926.         /* We are waiting for an outgoing message to complete. We
  1927.             can't send the next message until it does complete */
  1928.  
  1929.         if (waitForOgmToComplete)
  1930.         {
  1931.             if (ogm_complete(&sendmsg))
  1932.             {
  1933.                 pmsg_unref(txup);    /* unref the message */
  1934.                 txup = 0;
  1935.                 waitForOgmToComplete = FALSE;
  1936.                 hdrPoolStk = 0;        /* recover all the inplace headers */
  1937.             }
  1938.         }
  1939.  
  1940.     /* if not sending, and not waiting for ogm to complete,
  1941.         flush anything waiting in the reentered-send queue */
  1942.  
  1943.         if (!txfp && txrp != txwp && !waitForOgmToComplete) {
  1944.             txup = txlist[txrp];
  1945.             if (++txrp >= sizeof(txlist)/sizeof(txlist[0]))
  1946.                 txrp = 0;
  1947.  
  1948.             txfp = txup->m_frag->fr_link;
  1949.             txfp = txfp->fr_buf ? txfp : 0;
  1950.             if (!(txpcbp = ttpcb_find(txup->m_dst))
  1951.             || txpcbp->tt_state != TTOPEN)
  1952.                 txpcbp = topvmd;
  1953.         }
  1954.  
  1955.         if (pvmdebmask & PDMMESSAGE) {
  1956.             pvmlogprintf("mxfer() txfp %d gotem %d tt_rxf %d\n",
  1957.                     (txfp ? 1 : 0), gotem, (topvmd->tt_rxf ? 1 : 0));
  1958.         }
  1959.     }
  1960.  
  1961.     return gotem;
  1962. }
  1963.  
  1964.  
  1965. /*    mroute()
  1966. *
  1967. *    Route a message to a destination / Receive incoming messages.
  1968. *    Returns when
  1969. *        Outgoing message (if any) fully sent AND
  1970. *        (Timed out waiting (tmout) OR
  1971. *            At least one message fully received)
  1972. *    Returns >= 0 the number of complete messages downloaded
  1973. *    (although some may have been consumed by message-handlers),
  1974. *    or negative on error.
  1975. *
  1976. *    If mroute() is reentered (mroute -> mxfer -> handler -> pvm_send),
  1977. *    it queues the message and returns immediately.
  1978. *    The enclosing mxfer() later sends any messages in this queue.
  1979. */
  1980.  
  1981. int
  1982. mroute(mid, dtid, tag, tmout)
  1983.     int mid;                /* message (or 0) */
  1984.     int dtid;                /* dest */
  1985.     int tag;                /* type tag */
  1986.     struct timeval *tmout;    /* get at least one message */
  1987. {
  1988.     static int alreadyhere = 0;    /* have i called myself? */
  1989.  
  1990.     struct ttpcb *pcbp;            /* pcb for foreign task */
  1991.     int s;                        /* socket */
  1992.     int sbf;                    /* temp TC_CONREQ message */
  1993.     struct pmsg *up, *up2;
  1994.     struct sockaddr_in sad;
  1995.     int l;
  1996. #ifdef SOCKLENISUINT
  1997.     size_t oslen;
  1998. #else
  1999.     int oslen;
  2000. #endif
  2001.     int cc = 0;
  2002.     int gotem = 0;                /* count of received messages */
  2003.     static struct timeval ztv = { 0, 0 };
  2004.     char *addr = 0;
  2005. #ifndef NOUNIXDOM
  2006.     struct sockaddr_un uns;
  2007.     char spath[LEN_OF_TMP_NAM];
  2008. #endif
  2009.  
  2010.     if (up = midtobuf(mid)) {
  2011.         up->m_dst = dtid;
  2012.         up->m_tag = tag;
  2013.     }
  2014.  
  2015.     if (alreadyhere) {
  2016.         if (up) {
  2017.             up->m_ref++;
  2018.             txlist[txwp] = up;
  2019.             if (++txwp >= sizeof(txlist)/sizeof(txlist[0]))
  2020.                 txwp = 0;
  2021.             if (txwp == txrp)
  2022.                 abort();
  2023.         }
  2024.  
  2025.         /* we can't wait around if reentered */
  2026.  
  2027.         if (!tmout || tmout->tv_sec || tmout->tv_usec)
  2028.             return PvmNotImpl;
  2029.  
  2030.         return 0;
  2031.     }
  2032.  
  2033.     alreadyhere = 1;
  2034.  
  2035.     /* if sending a message, decide whether we need to route it. */
  2036.  
  2037.     /* Direct Routing is being set up in this section of code  
  2038.      * For workstations (not MPP, SHMEM) 
  2039.      *    either Unix domain or TCP sockets are used.
  2040.      *  task exit notifies are set up for route closure
  2041.      *
  2042.      * For MPPs and SHMEM,
  2043.       *    connections to local tasks are always direct and require no
  2044.      *    handshake negotiation. 
  2045.     */
  2046.  
  2047.     if (up) {        /*  We've got something to send */ 
  2048.  
  2049. #if !defined(IMA_MPP) /* This is the workstation direct route setup */
  2050.  
  2051.         /* Checks made (Workstation):
  2052.           *    o route option is direct
  2053.          *    o destination is given 
  2054.          *    o destination is a task
  2055.          *  o destination is not me
  2056.          *  o could not find task process control block     
  2057.         */
  2058.  
  2059.         if (pvmrouteopt == PvmRouteDirect
  2060.             && dtid
  2061.             && TIDISTASK(dtid)
  2062.             && dtid != pvmmytid
  2063.             && !ttpcb_find(dtid))
  2064.         {
  2065.  
  2066. #if !defined(NOUNIXDOM)
  2067.             /* Create a UNIX domain socket to build the direct route */
  2068.  
  2069.             if ((pvmmytid & TIDHOST) == (dtid & TIDHOST)) {
  2070.                 if ((s = socket(AF_UNIX, SOCK_STREAM, 0)) == -1) {
  2071.                     pvmlogperror("mroute() socket");
  2072.  
  2073.                 } else {
  2074.                     (void)TMPNAMFUN(spath);
  2075.                     BZERO((char*)&uns, sizeof(uns));
  2076.                     uns.sun_family = AF_UNIX;
  2077.                     spath[0] = 0;
  2078.                     (void)tmpnam(spath);
  2079.                     strcpy(uns.sun_path, spath);
  2080.  
  2081.                     if (bind(s, (struct sockaddr*)&uns, sizeof(uns)) == -1) {
  2082.                         pvmlogperror("mroute() bind");
  2083.                         (void)close(s);
  2084.                         s = -1;
  2085.  
  2086.                     } else {
  2087.                         pcbp = ttpcb_creat(dtid);
  2088.                         pcbp->tt_fd = s;
  2089.                         addr = pcbp->tt_spath = STRALLOC(spath);
  2090.                         pcbp->tt_state = TTCONWAIT;
  2091.                     }
  2092.                 }
  2093.  
  2094.             } else {
  2095. #endif /* !NOUNIXDOM */
  2096.             /* Open a TCP direct Connection here, instead */
  2097.  
  2098.                 if ((s = socket(AF_INET, SOCK_STREAM, 0)) == -1) {
  2099.                     pvmlogperror("mroute() socket");
  2100.  
  2101.                 } else {
  2102.                     sad = pvmourinet;
  2103.                     oslen = sizeof(sad);
  2104.                     if (bind(s, (struct sockaddr*)&sad, sizeof(sad)) == -1) {
  2105.                         pvmlogperror("mroute() bind");
  2106.                         (void)close(s);
  2107.                         s = -1;
  2108.  
  2109.                     } else {
  2110.                         if (getsockname(s, (struct sockaddr*)&sad, &oslen) == -1) {
  2111.                             pvmlogperror("mroute() getsockname");
  2112.                             (void)close(s);
  2113.                             s = -1;
  2114.  
  2115.                         } else {
  2116. #ifndef NOSOCKOPT
  2117.                             l = 1;
  2118.                             if (setsockopt(s, IPPROTO_TCP, TCP_NODELAY,
  2119.                                     (char*)&l, sizeof(int)) == -1)
  2120.                                 pvmlogperror("mroute() setsockopt");
  2121.                             l = TTSOCKBUF;
  2122.                             if (setsockopt(s, SOL_SOCKET, SO_SNDBUF,
  2123.                                     (char*)&l, sizeof(l)) == -1
  2124.                             || setsockopt(s, SOL_SOCKET, SO_RCVBUF,
  2125.                                     (char*)&l, sizeof(l)) == -1)
  2126.                                 pvmlogperror("mroute() setsockopt SO_SNDBUF");
  2127. #endif
  2128.                             pcbp = ttpcb_creat(dtid);
  2129.                             pcbp->tt_fd = s;
  2130.                             pcbp->tt_sad = sad;
  2131.                             pcbp->tt_state = TTCONWAIT;
  2132.                             addr = inadport_hex(&sad);
  2133.                         }
  2134.                     }
  2135.                 }
  2136. #if !defined(NOUNIXDOM)
  2137.             }
  2138. #endif
  2139.  
  2140.             /* 1. Request direct connection  (TC_CONREQ)
  2141.              * 2. Request Notify so that we can close dead routes 
  2142.              */              
  2143.             if (s >= 0) {  /* Socket was opened correctly */ 
  2144.  
  2145.         /* Send Connection Request */
  2146.                 sbf = pvm_setsbuf(pvm_mkbuf(PvmDataFoo));
  2147.                 l = TDPROTOCOL;
  2148.                 pvm_pkint(&l, 1, 1);
  2149.                 pvm_pkstr(addr);
  2150.                 sbf = pvm_setsbuf(sbf);
  2151.                 up2 = midtobuf(sbf);
  2152.                 up2->m_dst = dtid;
  2153.                 up2->m_tag = TC_CONREQ;
  2154.                 up2->m_ctx = SYSCTX_TC;
  2155.                 cc = mxfer(up2, &ztv);
  2156.                 pvm_freebuf(sbf);
  2157.  
  2158.         /* now send a task exit notify to my pvmd */
  2159.                 if (cc >= 0) {
  2160.                     gotem += cc;
  2161.                     sbf = pvm_setsbuf(pvm_mkbuf(PvmDataFoo));
  2162.                     l = PvmTaskExit;
  2163.                     pvm_pkint(&l, 1, 1);
  2164.                     l = SYSCTX_TC;
  2165.                     pvm_pkint(&l, 1, 1);
  2166.                     l = TC_TASKEXIT;
  2167.                     pvm_pkint(&l, 1, 1);
  2168.                     l = 1;
  2169.                     pvm_pkint(&l, 1, 1);
  2170.                     pvm_pkint(&dtid, 1, 1);
  2171.                     sbf = pvm_setsbuf(sbf);
  2172.                     up2 = midtobuf(sbf);
  2173.                     up2->m_dst = TIDPVMD;
  2174.                     up2->m_tag = TM_NOTIFY;
  2175.                     up2->m_ctx = SYSCTX_TM;
  2176.                     cc = mxfer(up2, &ztv);
  2177.                     pvm_freebuf(sbf);
  2178.                 }
  2179.  
  2180.                 if (pvmdebmask & PDMROUTE) {
  2181.                     pvmlogprintf("mroute() CONREQ to t%x\n", dtid);
  2182.                 }
  2183.  
  2184.     /* wait until the route pcb changes state */
  2185.  
  2186.                 while (pcbp->tt_state == TTCONWAIT) {
  2187.                     if ((cc = mxfer((struct pmsg *)0, (struct timeval *)0)) < 0)
  2188.                         break;
  2189.                     gotem += cc;
  2190.                 }
  2191.                 if (pcbp->tt_state == TTOPEN)
  2192.                     check_routeadd(pcbp);
  2193.             }
  2194.         }
  2195. #endif /* IMA_MPP */
  2196.     }
  2197.  
  2198.     /* now send the original message with whatever route we have */
  2199.  
  2200.     if (cc >= 0)
  2201.         if ((cc = mxfer(up, tmout)) > 0)
  2202.             gotem += cc;
  2203.  
  2204.     /* clean up any stale route pcbs */
  2205.  
  2206. #if !defined(IMA_MPP)
  2207.     pcbp = ttlist->tt_link;
  2208.     while (pcbp != ttlist)
  2209.         if (pcbp->tt_state == TTDEAD) {
  2210.             if (pvmdebmask & PDMROUTE) {
  2211.                 pvmlogprintf("mroute() freeing pcb t%x\n", pcbp->tt_tid);
  2212.             }
  2213.             pcbp = pcbp->tt_link;
  2214.             ttpcb_delete(pcbp->tt_rlink);
  2215.         } else
  2216.             pcbp = pcbp->tt_link;
  2217. #endif /* IMA_MPP */
  2218.  
  2219.     alreadyhere = 0;
  2220.     return (cc < 0 ? cc : gotem);
  2221. }
  2222.  
  2223.  
  2224. /*    msendrecv()
  2225. *
  2226. *    Single op to send a system message (usually to our pvmd) and get
  2227. *    the reply.
  2228. *    Returns message handle or negative if error.
  2229. */
  2230.  
  2231. int
  2232. msendrecv(other, tag, context)
  2233.     int other;                /* dst, src tid */
  2234.     int tag;                /* message tag */
  2235.     int context;            /* context to use for the message */
  2236. {
  2237.     static int nextwaitid = 1;
  2238.  
  2239.     int cc;
  2240.     struct pmsg *up;
  2241.  
  2242.     if (!pvmsbuf)
  2243.         return PvmNoBuf;
  2244.  
  2245.     /* send message to other */
  2246.     if (pvmdebmask & PDMMESSAGE) {
  2247.         pvmlogprintf("msendrecv() to t%x tag %s\n", other,
  2248.                 pvmnametag(tag, (int *)0));
  2249.     }
  2250.  
  2251.     pvmsbuf->m_wid = nextwaitid++;
  2252.     pvmsbuf->m_ctx = context;
  2253. /*
  2254.     pvmlogprintf("msendrecv() ctx=%d\n", pvmsbuf->m_ctx);
  2255. */
  2256.     if ((cc = mroute(pvmsbuf->m_mid, other, tag, (struct timeval *)0)) < 0)
  2257.         return cc;
  2258.  
  2259.     /* recv matching message from other */
  2260.     for (up = pvmrxlist->m_link; 1; up = up->m_link) {
  2261.         if (up == pvmrxlist) {
  2262.             up = up->m_rlink;
  2263.             if ((cc = mroute(0, 0, 0, (struct timeval *)0)) < 0)
  2264.                 return cc;
  2265.             up = up->m_link;
  2266.             if (up == pvmrxlist)
  2267.                 continue;
  2268.         }
  2269.  
  2270.         if (pvmdebmask & PDMMESSAGE) {
  2271.             pvmlogprintf("msendrecv() from t%x tag %s\n",
  2272.                     up->m_src, pvmnametag(up->m_tag, (int *)0));
  2273.         }
  2274.         if (up->m_src == other && up->m_tag == tag) {
  2275.             if (up->m_ctx != pvmsbuf->m_ctx) {
  2276.                 pvmlogprintf("msendrecv() tag %s, context doesn't match\n",
  2277.                         pvmnametag(up->m_tag, (int *)0));
  2278.             }
  2279.             if (up->m_wid != pvmsbuf->m_wid) {
  2280.                 pvmlogprintf("msendrecv() tag %s, waitid doesn't match\n",
  2281.                         pvmnametag(up->m_tag, (int *)0));
  2282.             }
  2283.             break;
  2284.         }
  2285.     }
  2286.     LISTDELETE(up, m_link, m_rlink);
  2287.     if (pvmrbuf)
  2288.         umbuf_free(pvmrbuf);
  2289.     pvmrbuf = 0;
  2290.     if (cc = pvm_setrbuf(up->m_mid))
  2291.         return cc;
  2292.     return up->m_mid;
  2293. }
  2294.  
  2295.  
  2296. static int
  2297. int_compare(i, j)
  2298. #if defined(IMA_SGI) || defined(IMA_SGI5) || defined(IMA_SGI64) || defined(IMA_SGIMP) || defined(IMA_SGIMP64)
  2299.     const void *i, *j;
  2300. #else
  2301.     void *i, *j;
  2302. #endif
  2303. {
  2304.     return *((int *)i) - *((int *)j);
  2305. }
  2306.  
  2307.  
  2308. /*    pvmmcast()
  2309. *
  2310. *    Multicast a message to a list of destinations.
  2311. */
  2312.  
  2313. int
  2314. pvmmcast(mid, tids, count, tag)
  2315.     int mid;    
  2316.     int *tids;
  2317.     int count;
  2318.     int tag;
  2319. {
  2320.     static struct timeval ztv = { 0, 0 };
  2321.  
  2322.     int *dst;
  2323.     int i, j;
  2324.     int cc = 0;
  2325.     struct ttpcb *pcbp;
  2326.     int sbf;
  2327.  
  2328.     /*
  2329.     * make sorted list of destinations
  2330.     */
  2331.     dst = TALLOC(count, int, "mcal");
  2332.     BCOPY(tids, dst, count * sizeof(int));
  2333.     qsort((char*)dst, count, sizeof(int), int_compare);
  2334.  
  2335.     /*
  2336.     * remove duplicates
  2337.     */
  2338.     j = 0;
  2339.     for (i = 1; i < count; i++)
  2340.         if (dst[i] != dst[j])
  2341.             dst[++j] = dst[i];
  2342.     count = j + 1;
  2343.  
  2344.     /* Need to set the context of the message buffer */
  2345.     pvmsbuf->m_ctx = pvmmyctx;
  2346.  
  2347.     /*
  2348.     * remove self from list
  2349.     * send over any direct routes we have
  2350.     *
  2351.     * XXX we should attempt new routes here if RouteDirect is on.
  2352.     */
  2353.     j = 0;
  2354.     for (i = 0; i < count; i++) {
  2355.         if (dst[i] == pvmmytid)
  2356.             continue;
  2357.         if ((pcbp = ttpcb_find(dst[i])) && pcbp->tt_state == TTOPEN)
  2358.             mroute(pvmsbuf->m_mid, dst[i], tag, &ztv);
  2359.         else
  2360.             dst[j++] = dst[i];
  2361.     }
  2362.     count = j;        /* destinations still to go */
  2363.  
  2364.     /*
  2365.     * send rest of addresses to pvmd for distribution
  2366.     */
  2367.     if (count > 0) {
  2368.         /* announce multicast address list to pvmd */
  2369.         sbf = pvm_setsbuf(pvm_mkbuf(PvmDataFoo));
  2370.         pvm_pkint(&count, 1, 1);
  2371.         pvm_pkint(dst, count, 1);
  2372.         sbf = pvm_setsbuf(sbf);
  2373.         if ((cc = mroute(sbf, TIDPVMD, TM_MCA, &ztv)) > 0)
  2374.             cc = 0;
  2375.         pvm_freebuf(sbf);
  2376.  
  2377.         /* send message */
  2378.         if (cc >= 0)
  2379.             if ((cc = mroute(pvmsbuf->m_mid, pvmmytid | TIDGID, tag, &ztv)) > 0)
  2380.                 cc = 0;
  2381.     }
  2382.  
  2383.     PVM_FREE(dst);
  2384.     return cc;
  2385. }
  2386.  
  2387.  
  2388. /*    mksocs()
  2389. *
  2390. *    Make socket for talking to pvmd.  Connect to address advertized
  2391. *    in pvmd socket-name file.
  2392. *
  2393. *    Returns 0 if okay, else error code.
  2394. */
  2395.  
  2396. static int
  2397. mksocs()
  2398. {
  2399.     char buf[128];
  2400. #ifndef WIN32
  2401.     int d;
  2402. #else
  2403.     HANDLE d;
  2404. #endif
  2405.  
  2406. #ifdef SOCKLENISUINT
  2407.     size_t oslen;
  2408. #else
  2409.     int oslen;
  2410. #endif
  2411.     int n;
  2412.     int try;
  2413.     char *p;
  2414. #ifndef NOUNIXDOM
  2415.     struct sockaddr_un uns;
  2416. #endif
  2417.  
  2418.     if (topvmd)
  2419.         return 0;
  2420.  
  2421.     /*
  2422.     * get addr of pvmd, make socket to talk.
  2423.     * first try envar PVMSOCK, then try sockaddr file.
  2424.     */
  2425.  
  2426.     if (!(p = getenv("PVMSOCK"))) {
  2427.         if (!(p = pvmdsockfile())) {
  2428.             pvmlogerror("mksocs() pvmdsockfile() failed\n");
  2429.             goto bail;
  2430.         }
  2431. #ifndef WIN32
  2432.         if ((d = open(p, O_RDONLY, 0)) == -1) {
  2433. #else 
  2434.         d = win32_open_file(p);
  2435.         if (d == (HANDLE) -2) {
  2436.             system_loser_win=TRUE;
  2437.             d = _open(p,O_RDONLY,0);
  2438.         }
  2439.         if (d== (HANDLE) -1) {
  2440. #endif
  2441.             pvmlogperror(p);
  2442.             goto bail;
  2443.         }
  2444. #ifdef WIN32
  2445.         if (!system_loser_win) {
  2446.             n = win32_read_file(d,buf,sizeof(buf));
  2447.             win32_close_file(d);
  2448.         }
  2449.         else  {
  2450.             n = _read(d,buf,sizeof(buf));
  2451.             (void)_close(d);
  2452.         }
  2453. #else
  2454.         n = read(d, buf, sizeof(buf));
  2455.         (void)close(d);
  2456. #endif
  2457.         if (n == -1) {
  2458.             pvmlogperror("mksocs() read addr file");
  2459.             goto bail;
  2460.         }
  2461.         if (n == 0) {
  2462.             pvmlogerror("mksocs() read addr file: wrong length read\n");
  2463.             goto bail;
  2464.         }
  2465.         buf[n] = 0;
  2466.         p = buf;
  2467.     }
  2468.  
  2469.     FD_ZERO(&pvmrfds);
  2470. /*
  2471.     FD_ZERO(&pvmwfds);
  2472. */
  2473.     pvmnfds = 0;
  2474.  
  2475.     topvmd = ttpcb_new();
  2476.     topvmd->tt_tid = TIDPVMD;
  2477.  
  2478.     if (p[0] == '/') {
  2479. #ifdef NOUNIXDOM
  2480.         pvmlogerror("mksocs() no support for Unix domain socket\n");
  2481.         goto bail;
  2482.  
  2483. #else /*NOUNIXDOM*/
  2484.         if ((topvmd->tt_fd = socket(AF_UNIX, SOCK_STREAM, 0)) == -1) {
  2485.             pvmlogperror("mksocs() socket");
  2486.             goto bail;
  2487.         }
  2488.  
  2489.     /*
  2490.     * XXX these 2 loops are a hack -
  2491.     * XXX it keeps too many tasks from overflowing the pvmd listen q.
  2492.     * XXX maybe the pvmd should make a socket pair for the task instead.
  2493.     */
  2494.         try = 5;
  2495.         while (1) {
  2496.             BZERO((char*)&uns, sizeof(uns));
  2497.             uns.sun_family = AF_UNIX;
  2498.             strcpy(uns.sun_path, p);
  2499.             n = sizeof(uns);
  2500.             if (connect(topvmd->tt_fd, (struct sockaddr*)&uns, n) == -1) {
  2501.                 if (--try <= 0) {
  2502.                     pvmlogperror("mksocs() connect");
  2503.                     goto bail;
  2504.                 }
  2505.                 sleep(1);    /* XXX hmm again */
  2506.  
  2507.             } else
  2508.                 break;
  2509.         }
  2510. #endif /*NOUNIXDOM*/
  2511.  
  2512.     } else {
  2513.         if ((topvmd->tt_fd = socket(AF_INET, SOCK_STREAM, 0)) == -1) {
  2514.             pvmlogperror("mksocs() socket");
  2515.             goto bail;
  2516.         }
  2517.  
  2518.         try = 5;
  2519.         while (1) {    /* goto is at the root of all good programming style */
  2520.             hex_inadport(p, &topvmd->tt_osad);
  2521.             topvmd->tt_osad.sin_family = AF_INET;
  2522.             n = sizeof(topvmd->tt_osad);
  2523.  
  2524.             if (connect(topvmd->tt_fd, (struct sockaddr*)&topvmd->tt_osad, n)
  2525.             == -1) {
  2526.                 if (--try <= 0) {
  2527.                     pvmlogperror("mksocs() connect");
  2528.                     goto bail;
  2529.                 }
  2530. #ifndef WIN32
  2531.                 sleep(1);    /* XXX hmm again */
  2532. #else
  2533.                 Sleep(1);
  2534. #endif    
  2535.             } else
  2536.                 break;
  2537.         }
  2538.  
  2539. #ifndef NOSOCKOPT
  2540.         d = 1;
  2541.         if (setsockopt(topvmd->tt_fd, IPPROTO_TCP, TCP_NODELAY, (char*)&d, sizeof(int))
  2542.         == -1) {
  2543.             pvmlogperror("mksocs() setsockopt");
  2544.             goto bail;
  2545.         }
  2546. #endif
  2547.         oslen = sizeof(topvmd->tt_sad);
  2548.         if (getsockname(topvmd->tt_fd, (struct sockaddr*)&topvmd->tt_sad, &oslen) == -1) {
  2549.             pvmlogperror("mksocs() getsockname");
  2550.             goto bail;
  2551.         }
  2552.     }
  2553.  
  2554.     topvmd->tt_state = TTOPEN;
  2555.     pvm_fd_add(topvmd->tt_fd, 1);
  2556.  
  2557.     return 0;
  2558.  
  2559. bail:
  2560.     if (topvmd)
  2561.         ttpcb_delete(topvmd);
  2562.     topvmd = 0;
  2563.     return PvmSysErr;
  2564. }
  2565.  
  2566.  
  2567. /*    unmksocs()
  2568. *
  2569. *    Close socket to local pvmd.
  2570. */
  2571.  
  2572. static int
  2573. unmksocs()
  2574. {
  2575.     if (!topvmd)
  2576.         return 1;
  2577.     while (ttlist->tt_link != ttlist)
  2578.         ttpcb_delete(ttlist->tt_link);
  2579.     ttpcb_delete(topvmd);
  2580.     topvmd = 0;
  2581.     return 0;
  2582. }
  2583.  
  2584.  
  2585. /*    pvmbeatask()
  2586. *
  2587. *    Initialize libpvm, config process as a task.
  2588. *    This is called as the first step of each libpvm function so no
  2589. *    explicit initialization is required.
  2590. *
  2591. *    Makes socket to talk to local pvmd, connects to pvmd, trades
  2592. *    config information and authentication.
  2593. *
  2594. *    Returns 0 if okay, else error code.
  2595. */
  2596.  
  2597. int
  2598. pvmbeatask()
  2599. {
  2600.     int sbf = 0, rbf = 0;            /* saved rx and tx message handles */
  2601.     int prver;                        /* protocol version */
  2602.     int cookie;                        /* cookie assigned by pvmd for ident */
  2603.     int cc;
  2604.     char authfn[LEN_OF_TMP_NAM];    /* auth file name */
  2605.     int authfd = -1;                /* auth fd to validate pvmd ident */
  2606.     int i;
  2607.     char buf[16];                    /* for converting sockaddr */
  2608.     char *p;
  2609.     struct pvmminfo minfo;
  2610.     int outtid, outctx, outtag;
  2611.     int trctid, trcctx, trctag;
  2612.     int need_trcinfo = 0;
  2613.     int new_tracer = 0;
  2614.     char tmask[ 2 * TEV_MASK_LENGTH ];
  2615.     int tbuf, topt;
  2616.     int mid;
  2617.     TEV_DECLS
  2618.  
  2619. /*
  2620.     pvm_setopt(PvmDebugMask, -1);
  2621. */
  2622.     if (pvmmytid != -1)
  2623.         return 0;
  2624.  
  2625.     pvmmydsig = pvmgetdsig();
  2626.  
  2627.     TEV_EXCLUSIVE;
  2628.  
  2629.     authfn[0] = 0;
  2630.  
  2631. #ifndef WIN32
  2632.     pvmmyupid = getpid();
  2633. #else
  2634.     pvmmyupid = _getpid();     /* .... */
  2635. #endif
  2636.  
  2637.     /*
  2638.     * get expected pid from environment in case we were started by
  2639.     * the pvmd and someone forked again
  2640.     */
  2641.  
  2642.     if (p = getenv("PVMEPID"))
  2643.         cookie = atoi(p);
  2644.     else
  2645.         cookie = 0;
  2646.  
  2647.     /* if ((pvm_useruid = getuid()) == -1) */
  2648.  
  2649. #ifndef WIN32
  2650.     if ((pvm_useruid = geteuid()) == -1) {
  2651.         pvmlogerror("can't getuid()\n");
  2652.         cc = PvmSysErr;
  2653.         goto bail2;
  2654.     }
  2655. #else
  2656.     if (!username)
  2657.         username = MyGetUserName();
  2658. #endif
  2659.  
  2660.     if (p = getenv("PVMTASKDEBUG")) {
  2661.         pvmdebmask = pvmstrtoi(p);
  2662.         if (pvmdebmask) {
  2663.             pvmlogprintf("task debug mask is 0x%x (%s)\n",
  2664.                     pvmdebmask, debug_flags(pvmdebmask));
  2665.         }
  2666.     }
  2667.  
  2668. #ifndef IMA_MPP
  2669.     if (cc = mksocs())        /* make socket to talk to pvmd */
  2670.         goto bail2;
  2671. #endif
  2672.  
  2673.     /*
  2674.     *    initialize received-message list
  2675.     */
  2676.  
  2677.     pvmrxlist = pmsg_new(1);
  2678.     BZERO((char*)pvmrxlist, sizeof(struct pmsg));
  2679.     pvmrxlist->m_link = pvmrxlist->m_rlink = pvmrxlist;
  2680.  
  2681.     ttlist = TALLOC(1, struct ttpcb, "tpcb");
  2682.     BZERO((char*)ttlist, sizeof(struct ttpcb));
  2683.     ttlist->tt_link = ttlist->tt_rlink = ttlist;
  2684.  
  2685.     sbf = pvm_setsbuf(pvm_mkbuf(PvmDataFoo));
  2686.     rbf = pvm_setrbuf(0);
  2687.  
  2688.     /*
  2689.     *    create empty t-auth file that pvmd must write and we'll check later
  2690.     */
  2691.  
  2692. #ifndef IMA_MPP
  2693.     (void)TMPNAMFUN(authfn);
  2694. #ifdef IMA_OS2
  2695.     if ((authfd = open(authfn, O_RDWR|O_CREAT|O_TRUNC, 0600)) == -1) {
  2696. #else
  2697.     if ((authfd = open(authfn, O_RDONLY|O_CREAT|O_TRUNC, 0600)) == -1) {
  2698. #endif
  2699.         pvmlogperror(authfn);
  2700.         pvmlogerror("pvmbeatask() can't creat t-auth file\n");
  2701.         cc = PvmSysErr;
  2702.         goto bail2;
  2703.     }
  2704.  
  2705.     /*
  2706.     *    send first connect message to pvmd
  2707.     */
  2708.  
  2709.     mxfersingle = 1;
  2710.     prver = TDPROTOCOL;
  2711.     pvm_pkint(&prver, 1, 1);
  2712.     pvm_pkstr(authfn);
  2713.     if ((cc = msendrecv(TIDPVMD, TM_CONNECT, SYSCTX_TM)) <= 0)
  2714.         goto bail;
  2715.     pvm_upkint(&prver, 1, 1);
  2716.     if (prver != TDPROTOCOL) {
  2717.         pvmlogprintf("pvmbeatask() t-d protocol mismatch (%d/%d)\n",
  2718.             TDPROTOCOL, prver);
  2719.         cc = PvmSysErr;
  2720.         goto bail;
  2721.     }
  2722.     pvm_upkint(&cc, 1, 1);
  2723.     if (!cc) {
  2724.         pvmlogerror("pvmbeatask() pvmd refuses connection\n");
  2725.         goto bail;
  2726.     }
  2727.  
  2728.     /*
  2729.     *    check our t-auth file; write in pvmd d-auth file
  2730.     */
  2731.  
  2732.     if ((cc = read(authfd, (char*)&cc, 1)) == -1) {
  2733.         pvmlogperror("pvmbeatask() read authfile");
  2734.         cc = PvmSysErr;
  2735.         goto bail;
  2736.     }
  2737.     if (cc != 1) {
  2738.         pvmlogerror("pvmbeatask() pvmd didn't validate itself\n");
  2739.         cc = PvmSysErr;
  2740.         goto bail;
  2741.     }
  2742.     (void)close(authfd);
  2743.     (void)unlink(authfn);
  2744.  
  2745.     pvm_upkstr(authfn);
  2746.     if ((authfd = open(authfn, O_WRONLY, 0)) == -1) {
  2747.         pvmlogperror(authfn);
  2748.         pvmlogerror("pvmbeatask() failed to open d-auth file\n");
  2749.         authfn[0] = 0;
  2750.         cc = PvmSysErr;
  2751.         goto bail;
  2752.     }
  2753.     cc = write(authfd, authfn, 1);
  2754.     (void)close(authfd);
  2755.     if (cc != 1) {
  2756.         if (cc == -1)
  2757.             pvmlogperror(authfn);
  2758.         pvmlogerror("pvmbeatask() can't write d-auth file\n");
  2759.         authfn[0] = 0;
  2760.         cc = PvmSysErr;
  2761.         goto bail;
  2762.     }
  2763.     authfd = -1;
  2764.     authfn[0] = 0;
  2765.  
  2766.     /*
  2767.     *    send second connect message to pvmd
  2768.     */
  2769.  
  2770.     pvm_initsend(PvmDataFoo);
  2771.     pvm_pkint(&pvmmyupid, 1, 1);
  2772.     pvm_pkint(&cookie, 1, 1);
  2773.     if ((cc = msendrecv(TIDPVMD, TM_CONN2, SYSCTX_TM)) <= 0)
  2774.         goto bail;
  2775.     pvm_upkint(&cc, 1, 1);
  2776.     if (!cc) {
  2777.         pvmlogerror("pvmbeatask() pvmd refuses connection\n");
  2778.         goto bail;
  2779.     }
  2780. #endif /* IMA_MPP */
  2781.  
  2782. #ifdef IMA_MPP
  2783.     pvm_mpp_beatask(&pvmmytid, &pvmmyptid, &outtid, &outctx, 
  2784.                 &outtag, &trctid, &trcctx,&trctag, &pvmudpmtu,
  2785.                 &pvmschedtid, &topvmd);
  2786. #else
  2787.     pvm_upkint(&pvmmytid, 1, 1);
  2788.     pvm_upkint(&pvmmyptid, 1, 1);
  2789.  
  2790.     pvm_upkint(&outtid, 1, 1);
  2791.     pvm_upkint(&outctx, 1, 1);
  2792.     pvm_upkint(&outtag, 1, 1);
  2793. #endif
  2794.     if (!pvmtrc.outtid) {
  2795.         pvmtrc.outtid = outtid;
  2796.         pvmtrc.outctx = outctx;
  2797.         pvmtrc.outtag = outtag;
  2798.         pvmctrc.outtid = pvmtrc.outtid;
  2799.         pvmctrc.outctx = pvmtrc.outctx;
  2800.         pvmctrc.outtag = pvmtrc.outtag;
  2801.     }
  2802.  
  2803. #ifndef IMA_MPP
  2804.     pvm_upkint(&trctid, 1, 1);
  2805.     pvm_upkint(&trcctx, 1, 1);
  2806.     pvm_upkint(&trctag, 1, 1);
  2807. #endif
  2808.     if (!pvmtrc.trctid) {
  2809.         pvmtrc.trctid = trctid;
  2810.         pvmtrc.trcctx = trcctx;
  2811.         pvmtrc.trctag = trctag;
  2812.         pvmctrc.trctid = pvmtrc.trctid;
  2813.         pvmctrc.trcctx = pvmtrc.trcctx;
  2814.         pvmctrc.trctag = pvmtrc.trctag;
  2815.         new_tracer++;
  2816.     }
  2817.  
  2818.     if (p = getenv("PVMCTX"))
  2819.         pvmmyctx = pvmstrtoi(p);
  2820. /* 
  2821.     if (pvmmyctx == 0)
  2822.         pvmmyctx = pvm_newcontext();
  2823. */
  2824.  
  2825.     /* get trace mask from envar or zero it */
  2826.  
  2827.     if ( (p = getenv("PVMTMASK")) ) {
  2828.         if ( strlen(p) + 1 == TEV_MASK_LENGTH )
  2829.             BCOPY(p, pvmtrc.tmask, TEV_MASK_LENGTH);
  2830.         else
  2831.             TEV_MASK_INIT(pvmtrc.tmask);
  2832.     } else {
  2833.         TEV_MASK_INIT(pvmtrc.tmask);
  2834.         if ( new_tracer ) need_trcinfo++;
  2835.     }
  2836.  
  2837.     BCOPY(pvmtrc.tmask, pvmctrc.tmask, TEV_MASK_LENGTH);
  2838.  
  2839.     /* get trace buffering from envar */
  2840.  
  2841.     if ((p = getenv("PVMTRCBUF")))
  2842.         pvmtrc.trcbuf = atoi( p );
  2843.     else {
  2844.         pvmtrc.trcbuf = 0;
  2845.         if ( new_tracer ) need_trcinfo++;
  2846.     }
  2847.  
  2848.     pvmctrc.trcbuf = pvmtrc.trcbuf;
  2849.  
  2850.     /* get trace options from envar */
  2851.  
  2852.     if ((p = getenv("PVMTRCOPT")))
  2853.         pvmtrc.trcopt = atoi( p );
  2854.     else {
  2855.         pvmtrc.trcopt = 0;
  2856.         if ( new_tracer ) need_trcinfo++;
  2857.     }
  2858.  
  2859.     pvmctrc.trcopt = pvmtrc.trcopt;
  2860.  
  2861. #ifndef IMA_MPP
  2862.     pvm_upkint(&pvmudpmtu, 1, 1);
  2863. #endif
  2864.     pvmfrgsiz = pvmudpmtu;
  2865.  
  2866. #ifndef IMA_MPP
  2867.     pvm_upkint(&i, 1, 1);    /* XXX data signature */
  2868.  
  2869.     pvm_upkstr(buf);
  2870.     hex_inadport(buf, &pvmourinet);
  2871.     pvmourinet.sin_family = AF_INET;
  2872.     pvmourinet.sin_port = 0;
  2873.  
  2874.     pvm_upkint(&pvmschedtid, 1, 1);
  2875. #endif
  2876.  
  2877.     wait_init(pvmmytid, TIDLOCAL);
  2878.  
  2879.     BZERO(&minfo, sizeof(minfo));
  2880.     minfo.src = -1;
  2881.     minfo.ctx = SYSCTX_TC;
  2882.     minfo.tag = TC_CONREQ;
  2883.     pvm_addmhf(minfo.src, minfo.tag, minfo.ctx, pvm_tc_conreq);
  2884.     minfo.tag = TC_CONACK;
  2885.     pvm_addmhf(minfo.src, minfo.tag, minfo.ctx, pvm_tc_conack);
  2886.     minfo.tag = TC_TASKEXIT;
  2887.     pvm_addmhf(minfo.src, minfo.tag, minfo.ctx, pvm_tc_taskexit);
  2888.     minfo.tag = TC_NOOP;
  2889.     pvm_addmhf(minfo.src, minfo.tag, minfo.ctx, pvm_tc_noop);
  2890.     minfo.tag = TC_SETTRACE;
  2891.     pvm_addmhf(minfo.src, minfo.tag, minfo.ctx, pvm_tc_settrace);
  2892.     minfo.tag = TC_SETTRCBUF;
  2893.     pvm_addmhf(minfo.src, minfo.tag, minfo.ctx, pvm_tc_settrcbuf);
  2894.     minfo.tag = TC_SETTRCOPT;
  2895.     pvm_addmhf(minfo.src, minfo.tag, minfo.ctx, pvm_tc_settrcopt);
  2896.     minfo.tag = TC_SETTMASK;
  2897.     pvm_addmhf(minfo.src, minfo.tag, minfo.ctx, pvm_tc_settmask);
  2898.     minfo.tag = TC_SIBLINGS;
  2899.     pvm_addmhf(minfo.src, minfo.tag, minfo.ctx, pvm_tc_siblings);
  2900.  
  2901.     pvm_freebuf(pvm_setrbuf(rbf));
  2902.     pvm_freebuf(pvm_setsbuf(sbf));
  2903.     mxfersingle = 0;
  2904.  
  2905.     if ( need_trcinfo )
  2906.     {
  2907.         rbf = pvm_setrbuf( 0 );
  2908.  
  2909.         if ( pvm_recvinfo( PVMTRACERCLASS, 0, PvmMboxDefault ) > 0 )
  2910.         {
  2911.             pvm_upkint(&trctid, 1, 1);
  2912.  
  2913.             pvm_upkint(&trcctx, 1, 1);
  2914.             pvm_upkint(&trctag, 1, 1);
  2915.  
  2916.             pvm_upkint(&outctx, 1, 1);  /* unused here */
  2917.             pvm_upkint(&outtag, 1, 1);  /* unused here */
  2918.  
  2919.             pvm_upkstr(tmask);
  2920.  
  2921.             pvm_upkint(&tbuf, 1, 1);
  2922.             pvm_upkint(&topt, 1, 1);
  2923.  
  2924.             if ( pvmtrc.trctid == trctid && pvmtrc.trcctx == trcctx
  2925.                     && pvmtrc.trctag == trctag )
  2926.             {
  2927.                 if ( strlen(tmask) + 1 == TEV_MASK_LENGTH ) {
  2928.                     BCOPY(tmask, pvmtrc.tmask, TEV_MASK_LENGTH);
  2929.                     BCOPY(pvmtrc.tmask, pvmctrc.tmask, TEV_MASK_LENGTH);
  2930.                 }
  2931.  
  2932.                 pvmtrc.trcbuf = tbuf;
  2933.                 pvmctrc.trcbuf = pvmtrc.trcbuf;
  2934.  
  2935.                 pvmtrc.trcopt = topt;
  2936.                 pvmctrc.trcopt = pvmtrc.trcopt;
  2937.             }
  2938.  
  2939.             pvm_freebuf(pvm_setrbuf(rbf));
  2940.         }
  2941.  
  2942.         else
  2943.             pvm_setrbuf(rbf);
  2944.     }
  2945.  
  2946.     tev_init();
  2947.  
  2948.     if (TEV_AMEXCL) {
  2949.         TEV_ENDEXCL;
  2950.     }
  2951.     return 0;
  2952.  
  2953. bail:
  2954.     if (pvm_getrbuf() > 0)
  2955.         pvm_freebuf(pvm_getrbuf());
  2956.     if (pvm_getsbuf() > 0)
  2957.         pvm_freebuf(pvm_getsbuf());
  2958.     pvm_setrbuf(rbf);
  2959.     pvm_setsbuf(sbf);
  2960.  
  2961. #ifndef IMA_MPP
  2962.     if (authfd != -1)
  2963.         (void)close(authfd);
  2964.     if (authfn[0])
  2965.         (void)unlink(authfn);
  2966.     unmksocs();
  2967. #endif
  2968.  
  2969. bail2:
  2970.     if (TEV_AMEXCL) {
  2971.         TEV_ENDEXCL;
  2972.     }
  2973.     return cc;
  2974. }
  2975.  
  2976.  
  2977. int
  2978. pvmendtask()
  2979. {
  2980.     if (pvmmytid != -1) {
  2981. #if !defined(IMA_MPP)
  2982.         unmksocs();
  2983. #endif
  2984.         pvmmytid = -1;
  2985.         pvmtrc.trctid = 0;
  2986.     }
  2987.  
  2988.     return 0;
  2989. }
  2990.  
  2991.  
  2992. void
  2993. check_for_exit(src)
  2994.     int src;
  2995. {
  2996. }
  2997.  
  2998.  
  2999. /************************
  3000.  **  Libpvm Functions  **
  3001.  **                    **
  3002.  ************************/
  3003.  
  3004.  
  3005. int
  3006. pvm_getfds(fds)        /* XXX this function kinda sucks */
  3007.     int **fds;            /* fd list return */
  3008. {
  3009.     static int *fdlist = 0;
  3010.     static int fdlen = 0;
  3011.     int cc;
  3012.     int nfds;
  3013.     struct ttpcb *pcbp;
  3014.     TEV_DECLS
  3015.  
  3016.     if (TEV_EXCLUSIVE) {
  3017.         if (TEV_DO_TRACE(TEV_GETFDS,TEV_EVENT_ENTRY))
  3018.             TEV_FIN;
  3019.     }
  3020.  
  3021.     if (!(cc = BEATASK)) {
  3022.         nfds = 1;
  3023.         for (pcbp = ttlist->tt_link; pcbp != ttlist; pcbp = pcbp->tt_link)
  3024.             if (pcbp->tt_state == TTOPEN || pcbp->tt_state == TTGRNWAIT)
  3025.                 nfds++;
  3026.  
  3027.         if (fdlen < nfds) {
  3028.             fdlen = (nfds * 3) / 2 + 1;
  3029.             if (fdlist)
  3030.                 fdlist = TREALLOC(fdlist, fdlen, int);
  3031.             else
  3032.                 fdlist = TALLOC(fdlen, int, "fdlist");
  3033.         }
  3034.  
  3035.         fdlist[0] = topvmd->tt_fd;
  3036.         nfds = 1;
  3037.         for (pcbp = ttlist->tt_link; pcbp != ttlist; pcbp = pcbp->tt_link)
  3038.             if (pcbp->tt_state == TTOPEN || pcbp->tt_state == TTGRNWAIT)
  3039.                 fdlist[nfds++] = pcbp->tt_fd;
  3040.         *fds = fdlist;
  3041.         cc = nfds;
  3042.     }
  3043.  
  3044.     if (TEV_AMEXCL) {
  3045.         if (TEV_DO_TRACE(TEV_GETFDS,TEV_EVENT_EXIT)) {
  3046.             TEV_PACK_INT( TEV_DID_CC, TEV_DATA_SCALAR, &cc, 1, 1 );
  3047.             if (cc > 0) {
  3048.                 TEV_PACK_INT( TEV_DID_FDS, TEV_DATA_ARRAY,
  3049.                     (int *)fdlist, nfds, 1 );
  3050.             }
  3051.             TEV_FIN;
  3052.         }
  3053.         TEV_ENDEXCL;
  3054.     }
  3055.  
  3056.     return (cc < 0 ? lpvmerr("pvm_getfds", cc) : cc);
  3057. }
  3058.  
  3059.  
  3060. int
  3061. pvm_start_pvmd(argc, argv, block)
  3062.     int argc;        /* number of args to pass to pvmd (>= 0) */
  3063.     char **argv;    /* args for pvmd or null */
  3064.     int block;        /* if true, don't return until add hosts are started */
  3065. {
  3066.     char *sfn;
  3067.     struct stat sb;
  3068.     int cc;
  3069.     char *fn;            /* file to exec */
  3070.     char **av;
  3071.     int pfd[2];
  3072.     int n;
  3073.     FILE *ff;
  3074.     char buf[128];
  3075.  
  3076. #ifdef WIN32
  3077.     char *pathending = "/lib/win32/pvmd3.exe";
  3078.     SECURITY_ATTRIBUTES saPipe;
  3079.     PROCESS_INFORMATION pi;
  3080.     STARTUPINFO si;  /* for CreateProcess call */
  3081.     HANDLE pvmdid;
  3082.     int i = 0;
  3083.     char cmd[256];
  3084. #endif
  3085.  
  3086.     TEV_DECLS;
  3087.  
  3088.     if (TEV_EXCLUSIVE) {
  3089.         if (pvmmytid != -1
  3090.                 && TEV_DO_TRACE(TEV_START_PVMD,TEV_EVENT_ENTRY)) {
  3091.             TEV_PACK_INT( TEV_DID_BF, TEV_DATA_SCALAR, &block, 1, 1 );
  3092.             TEV_PACK_STRING( TEV_DID_AS, TEV_DATA_ARRAY,
  3093.                 argv, argc, 1 );
  3094.             TEV_FIN;
  3095.         }
  3096.     }
  3097.  
  3098.     if (argc < 0 || !argv)
  3099.         argc = 0;
  3100.  
  3101. #ifndef WIN32
  3102.     if ((pvm_useruid = getuid()) == -1) {
  3103.         pvmlogerror("can't getuid()\n");
  3104.         cc = PvmSysErr;
  3105.         goto bail;
  3106.     }
  3107. #else
  3108.     if (!username) 
  3109.         username = MyGetUserName();
  3110. #endif
  3111.  
  3112.     if (!(sfn = pvmdsockfile())) {
  3113.         pvmlogerror("pvm_start_pvmd() pvmdsockfile() failed\n");
  3114.         cc = PvmSysErr;
  3115.         goto bail;
  3116.     }
  3117.  
  3118.     if (stat(sfn, &sb) != -1) {
  3119.         cc = PvmDupHost;
  3120.         goto bail;
  3121.     }
  3122.  
  3123. #ifdef WIN32 
  3124.  
  3125.     cc = PvmSysErr;
  3126.  
  3127.     fn = malloc(128 * sizeof(char));
  3128.     
  3129.     strcpy(fn,(char *) pvmgetroot());
  3130.     strcat(fn,(char *) pathending);
  3131.     
  3132.     av = TALLOC(argc + 2, char *, "argv");
  3133.     if (argc > 0)
  3134.         BCOPY((char *)&argv[0], (char *)&av[1], argc * sizeof(char*));
  3135.     av[0] = fn;
  3136.     if (stat(av[0],&sb) == -1) {
  3137.         fprintf(stderr,"Couldn't find daemon executable !\n");
  3138.         goto bail;
  3139.     }
  3140.     av[argc + 1] = 0;
  3141.  
  3142.     strcpy(cmd,"");
  3143.     for (i=0;i <= argc ;i++) {    
  3144.         strcat(cmd,av[i]);
  3145.         strcat(cmd," ");
  3146.     }
  3147.  
  3148.     /* pvmdid gives us back the process handle 
  3149.         but it is an int anyway     */
  3150.     
  3151.     saPipe.nLength = sizeof(SECURITY_ATTRIBUTES);
  3152.     saPipe.lpSecurityDescriptor = NULL;
  3153.     saPipe.bInheritHandle = FALSE;
  3154.  
  3155.     memset(&si, 0, sizeof(si));
  3156.     si.cb = sizeof(si);
  3157.     pvmdid = (HANDLE) CreateProcess(
  3158.             av[0],                /* filename */
  3159.             cmd,                /* full command line for child */
  3160.                                 /* for example : hostfiles */
  3161.             NULL,                /* process security descriptor */
  3162.             NULL,                /* thread security descriptor */
  3163.             FALSE,                /* inherit handles? */
  3164.             DETACHED_PROCESS,    /* creation flags */
  3165.             NULL,                /* inherited environment address */
  3166.             NULL,                /* startup dir */
  3167.                                 /* NULL = start in current */
  3168.             &si,                /* pointer to startup info (input) */
  3169.             &pi);                /* pointer to process info (output) */
  3170.         
  3171.     if (!pvmdid) {
  3172.         fprintf(stderr,"CreateProcess() failed \n");
  3173.         fprintf(stderr,"enough memory ?\n");
  3174.         goto bail;
  3175.         return 1;
  3176.     }
  3177.  
  3178.     CloseHandle(pi.hThread);
  3179.     CloseHandle(pi.hProcess);
  3180.            
  3181.     PVM_FREE(av);
  3182.  
  3183.     while (stat(sfn, &sb) == -1)
  3184.         Sleep(5000);        /* what a hack */
  3185.  
  3186. #else
  3187.  
  3188. #ifdef    IMA_TITN
  3189.     if (socketpair(AF_UNIX, SOCK_STREAM, 0, pfd) == -1)
  3190. #else
  3191.     if (pipe(pfd) == -1)
  3192. #endif
  3193.     {
  3194.         cc = PvmSysErr;
  3195.         goto bail;
  3196.     }
  3197.  
  3198.     fn = pvmgetpvmd();
  3199.  
  3200.     av = TALLOC(argc + 2, char *, "argv");
  3201.     if (argc > 0)
  3202.         BCOPY((char *)&argv[0], (char *)&av[1], argc * sizeof(char*));
  3203.     av[0] = fn;
  3204.     av[argc + 1] = 0;
  3205.  
  3206.     if (!fork()) {
  3207.         (void)close(pfd[0]);
  3208.     /* fork again so the pvmd is not the child - won't have to wait() for it */
  3209.         if (!fork()) {
  3210.             if (pfd[1] != 1)
  3211.                 dup2(pfd[1], 1);
  3212.             for (n = getdtablesize(); n-- > 0; )
  3213.                 if (n != 1)
  3214.                     (void)close(n);
  3215.             (void)open("/dev/null", O_RDONLY, 0);    /* should be 0 */
  3216.             (void)open("/dev/null", O_WRONLY, 0);    /* should be 2 */
  3217.             (void)signal(SIGINT, SIG_IGN);
  3218.             (void)signal(SIGQUIT, SIG_IGN);
  3219. #ifndef IMA_OS2
  3220.             (void)signal(SIGTSTP, SIG_IGN);
  3221. #endif
  3222. #ifdef IMA_OS2
  3223.                         sprintf(buf,"%s/lib/%s/pvmd3.exe",
  3224.                                     getenv("PVM_ROOT"),getenv("PVM_ARCH")); 
  3225.                         av[0]=buf; 
  3226. #endif
  3227.             execvp(av[0], av);
  3228.         }
  3229.         _exit(0);
  3230.     }
  3231.     (void)close(pfd[1]);
  3232.     (void)wait(0);
  3233.     PVM_FREE(av);
  3234.  
  3235.     if (!(ff = fdopen(pfd[0], "r"))) {
  3236.         cc = PvmSysErr;
  3237.         (void)close(pfd[0]);
  3238.         goto bail;
  3239.     }
  3240.  
  3241.     strcpy(buf, "PVMSOCK=");
  3242.     n = strlen(buf);
  3243.     if (!fgets(buf + n, sizeof(buf) - n - 1, ff)) {
  3244.         cc = PvmCantStart;
  3245.         fclose(ff);
  3246.         goto bail;
  3247.     }
  3248.     fclose(ff);
  3249.     if (strlen(buf + n) < 2) {
  3250.         cc = PvmCantStart;
  3251.         goto bail;
  3252.     }
  3253.     n = strlen(buf);
  3254.     if (buf[n - 1] == '\n')
  3255.         buf[n - 1] = 0;
  3256.     pvmputenv(STRALLOC(buf));
  3257.  
  3258.     /* fprintf(stderr, "pvm_start_pvmd: %s\n", buf); */
  3259.  
  3260. #endif
  3261.  
  3262.     if (cc = BEATASK)
  3263.         goto bail;
  3264.  
  3265.     if (block) {
  3266.         struct pvmhostinfo *hip;
  3267.         int t = 1;
  3268.  
  3269.         pvm_config((int*)0, (int*)0, &hip);
  3270.         while ((cc = pvm_addhosts(&hip[0].hi_name, 1, (int*)0)) == PvmAlready) {
  3271. #ifndef WIN32
  3272.             sleep(t);
  3273. #else
  3274.             Sleep(t);
  3275. #endif
  3276.             if (t < 8)
  3277.                 t *= 2;
  3278.         }
  3279.         if (cc != PvmDupHost)
  3280.             goto bail;
  3281.         cc = BEATASK;
  3282.     }
  3283.  
  3284. bail:
  3285.  
  3286.     if (TEV_AMEXCL) {
  3287.         if (TEV_DO_TRACE(TEV_START_PVMD,TEV_EVENT_EXIT)) {
  3288.             TEV_PACK_INT( TEV_DID_CC, TEV_DATA_SCALAR, &cc, 1, 1 );
  3289.             TEV_FIN;
  3290.         }
  3291.         TEV_ENDEXCL;
  3292.     }
  3293.  
  3294.     return (cc < 0 ? lpvmerr("pvm_start_pvmd", cc) : 0);
  3295. }
  3296.  
  3297.  
  3298. int
  3299. pvm_precv(tid, tag, cp, len, dt, rtid, rtag, rlen)
  3300.     int tid;
  3301.     int tag;
  3302.     void *cp;
  3303.     int len;
  3304.     int dt;
  3305.     int *rtid;
  3306.     int *rtag;
  3307.     int *rlen;
  3308. {
  3309.     int nb, mc, src;
  3310.     int rbf;
  3311.     int cc = 0;
  3312.     long ad;
  3313.     TEV_DECLS
  3314.  
  3315.     if (TEV_EXCLUSIVE) {
  3316.         if (TEV_DO_TRACE(TEV_PRECV,TEV_EVENT_ENTRY)) {
  3317.             TEV_PACK_INT( TEV_DID_RST, TEV_DATA_SCALAR, &tid, 1, 1 );
  3318.             TEV_PACK_INT( TEV_DID_RMC, TEV_DATA_SCALAR, &tag, 1, 1 );
  3319.             ad = (long)cp;
  3320.             TEV_PACK_LONG( TEV_DID_PDA, TEV_DATA_SCALAR, &ad, 1, 1 );
  3321.             TEV_PACK_INT( TEV_DID_PC, TEV_DATA_SCALAR, &len, 1, 1 );
  3322.             TEV_PACK_INT( TEV_DID_PDT, TEV_DATA_SCALAR, &dt, 1, 1 );
  3323.             TEV_FIN;
  3324.         }
  3325.     }
  3326.  
  3327.     switch (dt) {
  3328.  
  3329.     case PVM_BYTE:
  3330.         len *= sizeof(char);
  3331.         break;
  3332.  
  3333.     case PVM_SHORT:
  3334.     case PVM_USHORT:
  3335.         len *= sizeof(short);
  3336.         break;
  3337.  
  3338.     case PVM_INT:
  3339.     case PVM_UINT:
  3340.         len *= sizeof(int);
  3341.         break;
  3342.  
  3343.     case PVM_LONG:
  3344.     case PVM_ULONG:
  3345.         len *= sizeof(long);
  3346.         break;
  3347.  
  3348.     case PVM_FLOAT:
  3349.         len *= sizeof(float);
  3350.         break;
  3351.  
  3352.     case PVM_CPLX:
  3353.         len *= sizeof(float) * 2;
  3354.         break;
  3355.  
  3356.     case PVM_DOUBLE:
  3357.         len *= sizeof(double);
  3358.         break;
  3359.  
  3360.     case PVM_DCPLX:
  3361.         len *= sizeof(double) * 2;
  3362.         break;
  3363.  
  3364.     case PVM_STR:
  3365.         cc = PvmNotImpl;
  3366.         break;
  3367.  
  3368.     default:
  3369.         cc = PvmBadParam;
  3370.         break;
  3371.     }
  3372.  
  3373.     if (!cc) {
  3374. #if !defined(IMA_MPP)
  3375.         rbf = pvm_setrbuf(0);
  3376.         cc = pvm_recv(tid, tag);
  3377.         if (cc > 0) {
  3378.             pvm_bufinfo(cc, &nb, &mc, &src);
  3379.             if (rlen)
  3380.                 *rlen = nb;
  3381.             if (nb < len)
  3382.                 len = nb;
  3383.             if (rtag)
  3384.                 *rtag = mc;
  3385.             if (rtid)
  3386.                 *rtid = src;
  3387.             pvm_upkbyte((char *)cp, len, 1);
  3388.             pvm_freebuf(cc);
  3389.             cc = 0;
  3390.         }
  3391.         pvm_setrbuf(rbf);
  3392. #else
  3393.         cc = pvm_mppprecv(tid, tag, cp ,len, dt, rtid, rtag, rlen);
  3394. #endif
  3395.     }
  3396.  
  3397.     if (TEV_AMEXCL) {
  3398.         if (TEV_DO_TRACE(TEV_PRECV,TEV_EVENT_EXIT)) {
  3399.             TEV_PACK_INT( TEV_DID_CC, TEV_DATA_SCALAR, &cc, 1, 1 );
  3400.             if ( cc < 0 )
  3401.                 nb = mc = src = -1;
  3402.             TEV_PACK_INT( TEV_DID_MNB, TEV_DATA_SCALAR, &nb, 1, 1 );
  3403.             TEV_PACK_INT( TEV_DID_MC, TEV_DATA_SCALAR, &mc, 1, 1 );
  3404.             TEV_PACK_INT( TEV_DID_SRC, TEV_DATA_SCALAR, &src, 1, 1 );
  3405.             TEV_FIN;
  3406.         }
  3407.         TEV_ENDEXCL;
  3408.     }
  3409.  
  3410.     if (cc < 0)
  3411.         lpvmerr("pvm_precv", cc);
  3412.     return cc;
  3413. }
  3414.  
  3415.  
  3416. int
  3417. pvm_psend(tid, tag, cp, len, dt)
  3418.     int tid;
  3419.     int tag;
  3420.     void *cp;
  3421.     int len;
  3422.     int dt;
  3423. {
  3424.     int sbf;
  3425.     int cc = 0;
  3426.     long ad;
  3427.     TEV_DECLS
  3428.  
  3429.     if (TEV_EXCLUSIVE) {
  3430.         if (TEV_DO_TRACE(TEV_PSEND,TEV_EVENT_ENTRY)) {
  3431.             TEV_PACK_INT( TEV_DID_DST, TEV_DATA_SCALAR, &tid, 1, 1 );
  3432.             TEV_PACK_INT( TEV_DID_MC, TEV_DATA_SCALAR, &tag, 1, 1 );
  3433.             ad = (long)cp;
  3434.             TEV_PACK_LONG( TEV_DID_PDA, TEV_DATA_SCALAR, &ad, 1, 1 );
  3435.             TEV_PACK_INT( TEV_DID_PC, TEV_DATA_SCALAR, &len, 1, 1 );
  3436.             TEV_PACK_INT( TEV_DID_PDT, TEV_DATA_SCALAR, &dt, 1, 1 );
  3437.             TEV_FIN;
  3438.         }
  3439.     }
  3440.  
  3441.     switch (dt) {
  3442.  
  3443.     case PVM_BYTE:
  3444.         len *= sizeof(char);
  3445.         break;
  3446.  
  3447.     case PVM_SHORT:
  3448.     case PVM_USHORT:
  3449.         len *= sizeof(short);
  3450.         break;
  3451.  
  3452.     case PVM_INT:
  3453.     case PVM_UINT:
  3454.         len *= sizeof(int);
  3455.         break;
  3456.  
  3457.     case PVM_LONG:
  3458.     case PVM_ULONG:
  3459.         len *= sizeof(long);
  3460.         break;
  3461.  
  3462.     case PVM_FLOAT:
  3463.         len *= sizeof(float);
  3464.         break;
  3465.  
  3466.     case PVM_CPLX:
  3467.         len *= sizeof(float) * 2;
  3468.         break;
  3469.  
  3470.     case PVM_DOUBLE:
  3471.         len *= sizeof(double);
  3472.         break;
  3473.  
  3474.     case PVM_DCPLX:
  3475.         len *= sizeof(double) * 2;
  3476.         break;
  3477.  
  3478.     case PVM_STR:
  3479.         cc = PvmNotImpl;
  3480.         break;
  3481.  
  3482.     default:
  3483.         cc = PvmBadParam;
  3484.         break;
  3485.     }
  3486.  
  3487. #if !defined(IMA_MPP)
  3488.     if (!cc) {
  3489.         sbf = pvm_setsbuf(pvm_mkbuf(PvmDataInPlace));
  3490.         pvm_pkbyte((char *)cp, len, 1);
  3491.         if ((cc = pvm_send(tid, tag)) > 0)
  3492.             cc = 0;
  3493.         pvm_freebuf(pvm_setsbuf(sbf));
  3494.     }
  3495. #else
  3496.     cc = pvm_mpppsend((char *) cp, len, tid, tag);
  3497. #endif
  3498.  
  3499.     if (TEV_AMEXCL) {
  3500.         if (TEV_DO_TRACE(TEV_PSEND,TEV_EVENT_EXIT)) {
  3501.             TEV_PACK_INT( TEV_DID_CC, TEV_DATA_SCALAR, &cc, 1, 1 );
  3502.             TEV_FIN;
  3503.         }
  3504.         TEV_ENDEXCL;
  3505.     }
  3506.  
  3507.     if (cc < 0)
  3508.         lpvmerr("pvm_psend", cc);
  3509.     return cc;
  3510. }
  3511.  
  3512. /* ----- ogm_complete ------ */
  3513. int 
  3514. ogm_complete( ogmlist )
  3515. struct msgid **ogmlist; 
  3516. {
  3517.  
  3518. struct msgid *mp, *oldmp, *head;
  3519.  
  3520. #if defined(IMA_MPP)
  3521.      if (!(mp = *ogmlist) )
  3522.         return TRUE;        /* there is nothing to check */
  3523.     
  3524.     /* go through the list message ids. checking if the message has
  3525.         complete. If the list is empty at the end, then return that
  3526.         message has finished */ 
  3527.  
  3528.     head = mp;
  3529.     mp = mp->ms_link;
  3530.     while (mp != head)
  3531.     {
  3532.         if ((*mp->mfunc->msgdone)(0, &(mp->id), mp->info))
  3533.         {
  3534.             mp = mp->ms_link;
  3535.             oldmp = mp->ms_rlink;
  3536.             LISTDELETE(oldmp,ms_link, ms_rlink)
  3537.             msgid_free(oldmp);
  3538.         }
  3539.         else
  3540.             mp = mp->ms_link;
  3541.         
  3542.     }
  3543.  
  3544.     /* mp now points to the head of the list */
  3545.     if ((*mp->mfunc->msgdone)(0, &(mp->id), mp->info))
  3546.     {
  3547.         if (mp->ms_link == mp)    /* the only one left */
  3548.         {
  3549.             msgid_free(mp);
  3550.             *ogmlist = (struct msgid *) NULL;
  3551.             return TRUE;
  3552.         }
  3553.         else
  3554.         {
  3555.             mp = mp->ms_link;
  3556.             oldmp = mp->ms_rlink;
  3557.             LISTDELETE(oldmp, ms_link, ms_rlink);
  3558.             msgid_free(oldmp);
  3559.             *ogmlist = mp;    /* new head of the message id list */
  3560.         }
  3561.     }    
  3562.     return FALSE;
  3563. #else
  3564.     return TRUE;    /* for workstations, the write is sychronous */
  3565. #endif
  3566. }
  3567.